react 0.8.0 → 0.9.0-rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -8
- package/addons.js +0 -3
- package/lib/AutoFocusMixin.js +30 -0
- package/lib/CSSCore.js +22 -21
- package/lib/CSSProperty.js +31 -0
- package/lib/ChangeEventPlugin.js +26 -4
- package/lib/ClientReactRootIndex.js +30 -0
- package/lib/CompositionEventPlugin.js +57 -9
- package/lib/DOMChildrenOperations.js +32 -2
- package/lib/DOMProperty.js +2 -0
- package/lib/DOMPropertyOperations.js +14 -1
- package/lib/Danger.js +8 -7
- package/lib/DefaultDOMPropertyConfig.js +12 -2
- package/lib/EnterLeaveEventPlugin.js +37 -4
- package/lib/EventConstants.js +3 -0
- package/lib/EventListener.js +42 -34
- package/lib/EventPluginHub.js +113 -12
- package/lib/EventPluginRegistry.js +39 -16
- package/lib/EventPluginUtils.js +32 -3
- package/lib/EventPropagators.js +6 -42
- package/lib/ExecutionEnvironment.js +3 -0
- package/lib/LinkedValueUtils.js +161 -0
- package/lib/PooledClass.js +6 -0
- package/lib/React.js +27 -3
- package/lib/ReactCSSTransitionGroup.js +65 -0
- package/lib/{ReactTransitionableChild.js → ReactCSSTransitionGroupChild.js} +21 -35
- package/lib/ReactComponent.js +87 -52
- package/lib/ReactComponentBrowserEnvironment.js +67 -49
- package/lib/ReactComponentEnvironment.js +2 -0
- package/lib/ReactCompositeComponent.js +547 -112
- package/lib/ReactContext.js +67 -0
- package/lib/ReactDOM.js +13 -0
- package/lib/ReactDOMButton.js +4 -0
- package/lib/ReactDOMComponent.js +46 -21
- package/lib/ReactDOMForm.js +9 -2
- package/lib/ReactDOMIDOperations.js +105 -60
- package/lib/ReactDOMImg.js +58 -0
- package/lib/ReactDOMInput.js +26 -14
- package/lib/ReactDOMOption.js +1 -0
- package/lib/ReactDOMSelect.js +36 -17
- package/lib/ReactDOMTextarea.js +12 -8
- package/lib/ReactDefaultInjection.js +50 -26
- package/lib/ReactDefaultPerf.js +207 -370
- package/lib/ReactDefaultPerfAnalysis.js +199 -0
- package/lib/ReactErrorUtils.js +5 -14
- package/lib/ReactEventEmitter.js +141 -145
- package/lib/ReactEventEmitterMixin.js +0 -32
- package/lib/ReactEventTopLevelCallback.js +32 -12
- package/lib/ReactInjection.js +39 -0
- package/lib/ReactInstanceHandles.js +35 -19
- package/lib/ReactLink.js +1 -1
- package/lib/ReactMount.js +127 -103
- package/lib/ReactMountReady.js +1 -1
- package/lib/ReactMultiChild.js +30 -46
- package/lib/ReactMultiChildUpdateTypes.js +2 -0
- package/lib/ReactOwner.js +10 -2
- package/lib/ReactPerf.js +5 -8
- package/lib/ReactPropTransferer.js +40 -21
- package/lib/ReactPropTypeLocationNames.js +31 -0
- package/lib/ReactPropTypeLocations.js +29 -0
- package/lib/ReactPropTypes.js +248 -47
- package/lib/ReactPutListenerQueue.js +61 -0
- package/lib/ReactReconcileTransaction.js +20 -0
- package/lib/ReactRootIndex.js +36 -0
- package/lib/ReactServerRendering.js +8 -11
- package/lib/ReactTextComponent.js +8 -3
- package/lib/{ReactTransitionKeySet.js → ReactTransitionChildMapping.js} +42 -47
- package/lib/ReactTransitionGroup.js +132 -57
- package/lib/ReactUpdates.js +14 -11
- package/lib/ReactWithAddons.js +7 -2
- package/lib/SelectEventPlugin.js +22 -39
- package/lib/ServerReactRootIndex.js +36 -0
- package/lib/SimpleEventPlugin.js +54 -6
- package/lib/SyntheticClipboardEvent.js +7 -1
- package/lib/SyntheticDragEvent.js +44 -0
- package/lib/SyntheticEvent.js +2 -1
- package/lib/SyntheticKeyboardEvent.js +4 -2
- package/lib/SyntheticWheelEvent.js +10 -7
- package/lib/Transaction.js +61 -36
- package/lib/cloneWithProps.js +59 -0
- package/lib/createArrayFrom.js +10 -13
- package/lib/createFullPageComponent.js +63 -0
- package/lib/cx.js +2 -2
- package/lib/flattenChildren.js +5 -2
- package/lib/getActiveElement.js +4 -3
- package/lib/getEventKey.js +85 -0
- package/lib/getMarkupWrap.js +10 -0
- package/lib/getTextContentAccessor.js +5 -3
- package/lib/getUnboundedScrollPosition.js +2 -2
- package/lib/invariant.js +12 -4
- package/lib/isEventSupported.js +7 -11
- package/lib/mergeHelpers.js +5 -6
- package/lib/onlyChild.js +43 -0
- package/lib/shouldUpdateReactComponent.js +58 -0
- package/lib/toArray.js +75 -0
- package/lib/traverseAllChildren.js +69 -7
- package/lib/warning.js +40 -0
- package/package.json +2 -3
- package/react.js +0 -3
- package/ReactJSErrors.js +0 -40
- package/lib/$.js +0 -46
- package/lib/CallbackRegistry.js +0 -91
- package/lib/LinkedValueMixin.js +0 -68
- package/lib/ex.js +0 -49
- package/lib/filterAttributes.js +0 -45
- package/lib/ge.js +0 -76
- package/lib/mutateHTMLNodeWithMarkup.js +0 -100
|
@@ -27,38 +27,6 @@ function runEventQueueInBatch(events) {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
var ReactEventEmitterMixin = {
|
|
30
|
-
/**
|
|
31
|
-
* Whether or not `ensureListening` has been invoked.
|
|
32
|
-
* @type {boolean}
|
|
33
|
-
* @private
|
|
34
|
-
*/
|
|
35
|
-
_isListening: false,
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Function, must be implemented. Listens to events on the top level of the
|
|
39
|
-
* application.
|
|
40
|
-
*
|
|
41
|
-
* @abstract
|
|
42
|
-
*
|
|
43
|
-
* listenAtTopLevel: null,
|
|
44
|
-
*/
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Ensures that top-level event delegation listeners are installed.
|
|
48
|
-
*
|
|
49
|
-
* There are issues with listening to both touch events and mouse events on
|
|
50
|
-
* the top-level, so we make the caller choose which one to listen to. (If
|
|
51
|
-
* there's a touch top-level listeners, anchors don't receive clicks for some
|
|
52
|
-
* reason, and only in some cases).
|
|
53
|
-
*
|
|
54
|
-
* @param {*} config Configuration passed through to `listenAtTopLevel`.
|
|
55
|
-
*/
|
|
56
|
-
ensureListening: function(config) {
|
|
57
|
-
if (!config.contentDocument._reactIsListening) {
|
|
58
|
-
this.listenAtTopLevel(config.touchNotMouse, config.contentDocument);
|
|
59
|
-
config.contentDocument._reactIsListening = true;
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
30
|
|
|
63
31
|
/**
|
|
64
32
|
* Streams a fired top-level event to `EventPluginHub` where plugins have the
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"use strict";
|
|
21
21
|
|
|
22
22
|
var ReactEventEmitter = require("./ReactEventEmitter");
|
|
23
|
+
var ReactInstanceHandles = require("./ReactInstanceHandles");
|
|
23
24
|
var ReactMount = require("./ReactMount");
|
|
24
25
|
|
|
25
26
|
var getEventTarget = require("./getEventTarget");
|
|
@@ -30,6 +31,24 @@ var getEventTarget = require("./getEventTarget");
|
|
|
30
31
|
*/
|
|
31
32
|
var _topLevelListenersEnabled = true;
|
|
32
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Finds the parent React component of `node`.
|
|
36
|
+
*
|
|
37
|
+
* @param {*} node
|
|
38
|
+
* @return {?DOMEventTarget} Parent container, or `null` if the specified node
|
|
39
|
+
* is not nested.
|
|
40
|
+
*/
|
|
41
|
+
function findParent(node) {
|
|
42
|
+
// TODO: It may be a good idea to cache this to prevent unnecessary DOM
|
|
43
|
+
// traversal, but caching is difficult to do correctly without using a
|
|
44
|
+
// mutation observer to listen for all DOM changes.
|
|
45
|
+
var nodeID = ReactMount.getID(node);
|
|
46
|
+
var rootID = ReactInstanceHandles.getReactRootIDFromNodeID(nodeID);
|
|
47
|
+
var container = ReactMount.findReactContainerForID(rootID);
|
|
48
|
+
var parent = ReactMount.getFirstReactDOM(container);
|
|
49
|
+
return parent;
|
|
50
|
+
}
|
|
51
|
+
|
|
33
52
|
/**
|
|
34
53
|
* Top-level callback creator used to implement event handling using delegation.
|
|
35
54
|
* This is used via dependency injection.
|
|
@@ -66,21 +85,22 @@ var ReactEventTopLevelCallback = {
|
|
|
66
85
|
if (!_topLevelListenersEnabled) {
|
|
67
86
|
return;
|
|
68
87
|
}
|
|
69
|
-
// TODO: Remove when synthetic events are ready, this is for IE<9.
|
|
70
|
-
if (nativeEvent.srcElement &&
|
|
71
|
-
nativeEvent.srcElement !== nativeEvent.target) {
|
|
72
|
-
nativeEvent.target = nativeEvent.srcElement;
|
|
73
|
-
}
|
|
74
88
|
var topLevelTarget = ReactMount.getFirstReactDOM(
|
|
75
89
|
getEventTarget(nativeEvent)
|
|
76
90
|
) || window;
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
topLevelTarget
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
91
|
+
|
|
92
|
+
// Loop through the hierarchy, in case there's any nested components.
|
|
93
|
+
while (topLevelTarget) {
|
|
94
|
+
var topLevelTargetID = ReactMount.getID(topLevelTarget) || '';
|
|
95
|
+
ReactEventEmitter.handleTopLevel(
|
|
96
|
+
topLevelType,
|
|
97
|
+
topLevelTarget,
|
|
98
|
+
topLevelTargetID,
|
|
99
|
+
nativeEvent
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
topLevelTarget = findParent(topLevelTarget);
|
|
103
|
+
}
|
|
84
104
|
};
|
|
85
105
|
}
|
|
86
106
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2013 Facebook, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
* @providesModule ReactInjection
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
"use strict";
|
|
20
|
+
|
|
21
|
+
var DOMProperty = require("./DOMProperty");
|
|
22
|
+
var EventPluginHub = require("./EventPluginHub");
|
|
23
|
+
var ReactDOM = require("./ReactDOM");
|
|
24
|
+
var ReactEventEmitter = require("./ReactEventEmitter");
|
|
25
|
+
var ReactPerf = require("./ReactPerf");
|
|
26
|
+
var ReactRootIndex = require("./ReactRootIndex");
|
|
27
|
+
var ReactUpdates = require("./ReactUpdates");
|
|
28
|
+
|
|
29
|
+
var ReactInjection = {
|
|
30
|
+
DOMProperty: DOMProperty.injection,
|
|
31
|
+
EventPluginHub: EventPluginHub.injection,
|
|
32
|
+
DOM: ReactDOM.injection,
|
|
33
|
+
EventEmitter: ReactEventEmitter.injection,
|
|
34
|
+
Perf: ReactPerf.injection,
|
|
35
|
+
RootIndex: ReactRootIndex.injection,
|
|
36
|
+
Updates: ReactUpdates.injection
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
module.exports = ReactInjection;
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
|
|
20
20
|
"use strict";
|
|
21
21
|
|
|
22
|
+
var ReactRootIndex = require("./ReactRootIndex");
|
|
23
|
+
|
|
22
24
|
var invariant = require("./invariant");
|
|
23
25
|
|
|
24
26
|
var SEPARATOR = '.';
|
|
@@ -29,15 +31,6 @@ var SEPARATOR_LENGTH = SEPARATOR.length;
|
|
|
29
31
|
*/
|
|
30
32
|
var MAX_TREE_DEPTH = 100;
|
|
31
33
|
|
|
32
|
-
/**
|
|
33
|
-
* Size of the reactRoot ID space. We generate random numbers for React root
|
|
34
|
-
* IDs and if there's a collision the events and DOM update system will
|
|
35
|
-
* get confused. If we assume 100 React components per page, and a user
|
|
36
|
-
* loads 1 page per minute 24/7 for 50 years, with a mount point space of
|
|
37
|
-
* 9,999,999 the likelihood of never having a collision is 99.997%.
|
|
38
|
-
*/
|
|
39
|
-
var GLOBAL_MOUNT_POINT_MAX = 9999999;
|
|
40
|
-
|
|
41
34
|
/**
|
|
42
35
|
* Creates a DOM ID prefix to use when mounting React components.
|
|
43
36
|
*
|
|
@@ -46,7 +39,7 @@ var GLOBAL_MOUNT_POINT_MAX = 9999999;
|
|
|
46
39
|
* @internal
|
|
47
40
|
*/
|
|
48
41
|
function getReactRootIDString(index) {
|
|
49
|
-
return SEPARATOR +
|
|
42
|
+
return SEPARATOR + index.toString(36);
|
|
50
43
|
}
|
|
51
44
|
|
|
52
45
|
/**
|
|
@@ -175,7 +168,8 @@ function getFirstCommonAncestorID(oneID, twoID) {
|
|
|
175
168
|
|
|
176
169
|
/**
|
|
177
170
|
* Traverses the parent path between two IDs (either up or down). The IDs must
|
|
178
|
-
* not be the same, and there must exist a parent path between them.
|
|
171
|
+
* not be the same, and there must exist a parent path between them. If the
|
|
172
|
+
* callback returns `false`, traversal is stopped.
|
|
179
173
|
*
|
|
180
174
|
* @param {?string} start ID at which to start traversal.
|
|
181
175
|
* @param {?string} stop ID at which to end traversal.
|
|
@@ -204,10 +198,11 @@ function traverseParentPath(start, stop, cb, arg, skipFirst, skipLast) {
|
|
|
204
198
|
var depth = 0;
|
|
205
199
|
var traverse = traverseUp ? getParentID : getNextDescendantID;
|
|
206
200
|
for (var id = start; /* until break */; id = traverse(id, stop)) {
|
|
201
|
+
var ret;
|
|
207
202
|
if ((!skipFirst || id !== start) && (!skipLast || id !== stop)) {
|
|
208
|
-
cb(id, traverseUp, arg);
|
|
203
|
+
ret = cb(id, traverseUp, arg);
|
|
209
204
|
}
|
|
210
|
-
if (id === stop) {
|
|
205
|
+
if (ret === false || id === stop) {
|
|
211
206
|
// Only break //after// visiting `stop`.
|
|
212
207
|
break;
|
|
213
208
|
}
|
|
@@ -229,10 +224,12 @@ function traverseParentPath(start, stop, cb, arg, skipFirst, skipLast) {
|
|
|
229
224
|
*/
|
|
230
225
|
var ReactInstanceHandles = {
|
|
231
226
|
|
|
227
|
+
/**
|
|
228
|
+
* Constructs a React root ID
|
|
229
|
+
* @return {string} A React root ID.
|
|
230
|
+
*/
|
|
232
231
|
createReactRootID: function() {
|
|
233
|
-
return getReactRootIDString(
|
|
234
|
-
Math.ceil(Math.random() * GLOBAL_MOUNT_POINT_MAX)
|
|
235
|
-
);
|
|
232
|
+
return getReactRootIDString(ReactRootIndex.createReactRootIndex());
|
|
236
233
|
},
|
|
237
234
|
|
|
238
235
|
/**
|
|
@@ -244,7 +241,7 @@ var ReactInstanceHandles = {
|
|
|
244
241
|
* @internal
|
|
245
242
|
*/
|
|
246
243
|
createReactID: function(rootID, name) {
|
|
247
|
-
return rootID +
|
|
244
|
+
return rootID + name;
|
|
248
245
|
},
|
|
249
246
|
|
|
250
247
|
/**
|
|
@@ -256,8 +253,11 @@ var ReactInstanceHandles = {
|
|
|
256
253
|
* @internal
|
|
257
254
|
*/
|
|
258
255
|
getReactRootIDFromNodeID: function(id) {
|
|
259
|
-
|
|
260
|
-
|
|
256
|
+
if (id && id.charAt(0) === SEPARATOR && id.length > 1) {
|
|
257
|
+
var index = id.indexOf(SEPARATOR, 1);
|
|
258
|
+
return index > -1 ? id.substr(0, index) : id;
|
|
259
|
+
}
|
|
260
|
+
return null;
|
|
261
261
|
},
|
|
262
262
|
|
|
263
263
|
/**
|
|
@@ -301,6 +301,22 @@ var ReactInstanceHandles = {
|
|
|
301
301
|
}
|
|
302
302
|
},
|
|
303
303
|
|
|
304
|
+
/**
|
|
305
|
+
* Traverse a node ID, calling the supplied `cb` for each ancestor ID. For
|
|
306
|
+
* example, passing `.0.$row-0.1` would result in `cb` getting called
|
|
307
|
+
* with `.0`, `.0.$row-0`, and `.0.$row-0.1`.
|
|
308
|
+
*
|
|
309
|
+
* NOTE: This traversal happens on IDs without touching the DOM.
|
|
310
|
+
*
|
|
311
|
+
* @param {string} targetID ID of the target node.
|
|
312
|
+
* @param {function} cb Callback to invoke.
|
|
313
|
+
* @param {*} arg Argument to invoke the callback with.
|
|
314
|
+
* @internal
|
|
315
|
+
*/
|
|
316
|
+
traverseAncestors: function(targetID, cb, arg) {
|
|
317
|
+
traverseParentPath('', targetID, cb, arg, true, false);
|
|
318
|
+
},
|
|
319
|
+
|
|
304
320
|
/**
|
|
305
321
|
* Exposed for unit testing.
|
|
306
322
|
* @private
|
package/lib/ReactLink.js
CHANGED
package/lib/ReactMount.js
CHANGED
|
@@ -18,17 +18,19 @@
|
|
|
18
18
|
|
|
19
19
|
"use strict";
|
|
20
20
|
|
|
21
|
+
var DOMProperty = require("./DOMProperty");
|
|
21
22
|
var ReactEventEmitter = require("./ReactEventEmitter");
|
|
22
23
|
var ReactInstanceHandles = require("./ReactInstanceHandles");
|
|
24
|
+
var ReactPerf = require("./ReactPerf");
|
|
23
25
|
|
|
24
|
-
var $ = require("./$");
|
|
25
26
|
var containsNode = require("./containsNode");
|
|
26
27
|
var getReactRootElementInContainer = require("./getReactRootElementInContainer");
|
|
27
28
|
var invariant = require("./invariant");
|
|
29
|
+
var shouldUpdateReactComponent = require("./shouldUpdateReactComponent");
|
|
28
30
|
|
|
29
31
|
var SEPARATOR = ReactInstanceHandles.SEPARATOR;
|
|
30
32
|
|
|
31
|
-
var ATTR_NAME =
|
|
33
|
+
var ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME;
|
|
32
34
|
var nodeCache = {};
|
|
33
35
|
|
|
34
36
|
var ELEMENT_NODE_TYPE = 1;
|
|
@@ -45,6 +47,9 @@ if ("production" !== process.env.NODE_ENV) {
|
|
|
45
47
|
var rootElementsByReactRootID = {};
|
|
46
48
|
}
|
|
47
49
|
|
|
50
|
+
// Used to store breadth-first search state in findComponentRoot.
|
|
51
|
+
var findComponentRootReusableArray = [];
|
|
52
|
+
|
|
48
53
|
/**
|
|
49
54
|
* @param {DOMElement} container DOM element that may contain a React component.
|
|
50
55
|
* @return {?string} A "reactRoot" ID, if a React component is rendered.
|
|
@@ -158,15 +163,45 @@ function purgeID(id) {
|
|
|
158
163
|
delete nodeCache[id];
|
|
159
164
|
}
|
|
160
165
|
|
|
166
|
+
var deepestNodeSoFar = null;
|
|
167
|
+
function findDeepestCachedAncestorImpl(ancestorID) {
|
|
168
|
+
var ancestor = nodeCache[ancestorID];
|
|
169
|
+
if (ancestor && isValid(ancestor, ancestorID)) {
|
|
170
|
+
deepestNodeSoFar = ancestor;
|
|
171
|
+
} else {
|
|
172
|
+
// This node isn't populated in the cache, so presumably none of its
|
|
173
|
+
// descendants are. Break out of the loop.
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Return the deepest cached node whose ID is a prefix of `targetID`.
|
|
180
|
+
*/
|
|
181
|
+
function findDeepestCachedAncestor(targetID) {
|
|
182
|
+
deepestNodeSoFar = null;
|
|
183
|
+
ReactInstanceHandles.traverseAncestors(
|
|
184
|
+
targetID,
|
|
185
|
+
findDeepestCachedAncestorImpl
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
var foundNode = deepestNodeSoFar;
|
|
189
|
+
deepestNodeSoFar = null;
|
|
190
|
+
return foundNode;
|
|
191
|
+
}
|
|
192
|
+
|
|
161
193
|
/**
|
|
162
194
|
* Mounting is the process of initializing a React component by creatings its
|
|
163
195
|
* representative DOM elements and inserting them into a supplied `container`.
|
|
164
196
|
* Any prior content inside `container` is destroyed in the process.
|
|
165
197
|
*
|
|
166
|
-
* ReactMount.renderComponent(
|
|
198
|
+
* ReactMount.renderComponent(
|
|
199
|
+
* component,
|
|
200
|
+
* document.getElementById('container')
|
|
201
|
+
* );
|
|
167
202
|
*
|
|
168
203
|
* <div id="container"> <-- Supplied `container`.
|
|
169
|
-
* <div data-reactid=".
|
|
204
|
+
* <div data-reactid=".3"> <-- Rendered reactRoot of React
|
|
170
205
|
* // ... component.
|
|
171
206
|
* </div>
|
|
172
207
|
* </div>
|
|
@@ -174,11 +209,6 @@ function purgeID(id) {
|
|
|
174
209
|
* Inside of `container`, the first element rendered is the "reactRoot".
|
|
175
210
|
*/
|
|
176
211
|
var ReactMount = {
|
|
177
|
-
/**
|
|
178
|
-
* Safety guard to prevent accidentally rendering over the entire HTML tree.
|
|
179
|
-
*/
|
|
180
|
-
allowFullPageRender: false,
|
|
181
|
-
|
|
182
212
|
/** Time spent generating markup. */
|
|
183
213
|
totalInstantiationTime: 0,
|
|
184
214
|
|
|
@@ -203,30 +233,6 @@ var ReactMount = {
|
|
|
203
233
|
renderCallback();
|
|
204
234
|
},
|
|
205
235
|
|
|
206
|
-
/**
|
|
207
|
-
* Ensures that the top-level event delegation listener is set up. This will
|
|
208
|
-
* be invoked some time before the first time any React component is rendered.
|
|
209
|
-
* @param {DOMElement} container container we're rendering into
|
|
210
|
-
*
|
|
211
|
-
* @private
|
|
212
|
-
*/
|
|
213
|
-
prepareEnvironmentForDOM: function(container) {
|
|
214
|
-
("production" !== process.env.NODE_ENV ? invariant(
|
|
215
|
-
container && (
|
|
216
|
-
container.nodeType === ELEMENT_NODE_TYPE ||
|
|
217
|
-
container.nodeType === DOC_NODE_TYPE
|
|
218
|
-
),
|
|
219
|
-
'prepareEnvironmentForDOM(...): Target container is not a DOM element.'
|
|
220
|
-
) : invariant(container && (
|
|
221
|
-
container.nodeType === ELEMENT_NODE_TYPE ||
|
|
222
|
-
container.nodeType === DOC_NODE_TYPE
|
|
223
|
-
)));
|
|
224
|
-
var doc = container.nodeType === ELEMENT_NODE_TYPE ?
|
|
225
|
-
container.ownerDocument :
|
|
226
|
-
container;
|
|
227
|
-
ReactEventEmitter.ensureListening(ReactMount.useTouchEvents, doc);
|
|
228
|
-
},
|
|
229
|
-
|
|
230
236
|
/**
|
|
231
237
|
* Take a component that's already mounted into the DOM and replace its props
|
|
232
238
|
* @param {ReactComponent} prevComponent component instance already in the DOM
|
|
@@ -254,13 +260,25 @@ var ReactMount = {
|
|
|
254
260
|
},
|
|
255
261
|
|
|
256
262
|
/**
|
|
257
|
-
* Register a component into the instance map and
|
|
263
|
+
* Register a component into the instance map and starts scroll value
|
|
264
|
+
* monitoring
|
|
258
265
|
* @param {ReactComponent} nextComponent component instance to render
|
|
259
266
|
* @param {DOMElement} container container to render into
|
|
260
267
|
* @return {string} reactRoot ID prefix
|
|
261
268
|
*/
|
|
262
269
|
_registerComponent: function(nextComponent, container) {
|
|
263
|
-
|
|
270
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
271
|
+
container && (
|
|
272
|
+
container.nodeType === ELEMENT_NODE_TYPE ||
|
|
273
|
+
container.nodeType === DOC_NODE_TYPE
|
|
274
|
+
),
|
|
275
|
+
'_registerComponent(...): Target container is not a DOM element.'
|
|
276
|
+
) : invariant(container && (
|
|
277
|
+
container.nodeType === ELEMENT_NODE_TYPE ||
|
|
278
|
+
container.nodeType === DOC_NODE_TYPE
|
|
279
|
+
)));
|
|
280
|
+
|
|
281
|
+
ReactEventEmitter.ensureScrollValueMonitoring();
|
|
264
282
|
|
|
265
283
|
var reactRootID = ReactMount.registerContainer(container);
|
|
266
284
|
instancesByReactRootID[reactRootID] = nextComponent;
|
|
@@ -274,25 +292,29 @@ var ReactMount = {
|
|
|
274
292
|
* @param {boolean} shouldReuseMarkup if we should skip the markup insertion
|
|
275
293
|
* @return {ReactComponent} nextComponent
|
|
276
294
|
*/
|
|
277
|
-
_renderNewRootComponent:
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
container
|
|
285
|
-
|
|
286
|
-
|
|
295
|
+
_renderNewRootComponent: ReactPerf.measure(
|
|
296
|
+
'ReactMount',
|
|
297
|
+
'_renderNewRootComponent',
|
|
298
|
+
function(
|
|
299
|
+
nextComponent,
|
|
300
|
+
container,
|
|
301
|
+
shouldReuseMarkup) {
|
|
302
|
+
var reactRootID = ReactMount._registerComponent(nextComponent, container);
|
|
303
|
+
nextComponent.mountComponentIntoNode(
|
|
304
|
+
reactRootID,
|
|
305
|
+
container,
|
|
306
|
+
shouldReuseMarkup
|
|
307
|
+
);
|
|
287
308
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
309
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
310
|
+
// Record the root element in case it later gets transplanted.
|
|
311
|
+
rootElementsByReactRootID[reactRootID] =
|
|
312
|
+
getReactRootElementInContainer(container);
|
|
313
|
+
}
|
|
293
314
|
|
|
294
|
-
|
|
295
|
-
|
|
315
|
+
return nextComponent;
|
|
316
|
+
}
|
|
317
|
+
),
|
|
296
318
|
|
|
297
319
|
/**
|
|
298
320
|
* Renders a React component into the DOM in the supplied `container`.
|
|
@@ -307,12 +329,12 @@ var ReactMount = {
|
|
|
307
329
|
* @return {ReactComponent} Component instance rendered in `container`.
|
|
308
330
|
*/
|
|
309
331
|
renderComponent: function(nextComponent, container, callback) {
|
|
310
|
-
var
|
|
332
|
+
var prevComponent = instancesByReactRootID[getReactRootID(container)];
|
|
311
333
|
|
|
312
|
-
if (
|
|
313
|
-
if (
|
|
334
|
+
if (prevComponent) {
|
|
335
|
+
if (shouldUpdateReactComponent(prevComponent, nextComponent)) {
|
|
314
336
|
return ReactMount._updateRootComponent(
|
|
315
|
-
|
|
337
|
+
prevComponent,
|
|
316
338
|
nextComponent,
|
|
317
339
|
container,
|
|
318
340
|
callback
|
|
@@ -326,14 +348,14 @@ var ReactMount = {
|
|
|
326
348
|
var containerHasReactMarkup =
|
|
327
349
|
reactRootElement && ReactMount.isRenderedByReact(reactRootElement);
|
|
328
350
|
|
|
329
|
-
var shouldReuseMarkup = containerHasReactMarkup && !
|
|
351
|
+
var shouldReuseMarkup = containerHasReactMarkup && !prevComponent;
|
|
330
352
|
|
|
331
353
|
var component = ReactMount._renderNewRootComponent(
|
|
332
354
|
nextComponent,
|
|
333
355
|
container,
|
|
334
356
|
shouldReuseMarkup
|
|
335
357
|
);
|
|
336
|
-
callback && callback();
|
|
358
|
+
callback && callback.call(component);
|
|
337
359
|
return component;
|
|
338
360
|
},
|
|
339
361
|
|
|
@@ -360,12 +382,18 @@ var ReactMount = {
|
|
|
360
382
|
* @return {ReactComponent} Component instance rendered in the container node.
|
|
361
383
|
*/
|
|
362
384
|
constructAndRenderComponentByID: function(constructor, props, id) {
|
|
363
|
-
|
|
385
|
+
var domNode = document.getElementById(id);
|
|
386
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
387
|
+
domNode,
|
|
388
|
+
'Tried to get element with id of "%s" but it is not present on the page.',
|
|
389
|
+
id
|
|
390
|
+
) : invariant(domNode));
|
|
391
|
+
return ReactMount.constructAndRenderComponent(constructor, props, domNode);
|
|
364
392
|
},
|
|
365
393
|
|
|
366
394
|
/**
|
|
367
395
|
* Registers a container node into which React components will be rendered.
|
|
368
|
-
* This also creates the "
|
|
396
|
+
* This also creates the "reactRoot" ID that will be assigned to the element
|
|
369
397
|
* rendered within.
|
|
370
398
|
*
|
|
371
399
|
* @param {DOMElement} container DOM element to register as a container.
|
|
@@ -407,20 +435,6 @@ var ReactMount = {
|
|
|
407
435
|
return true;
|
|
408
436
|
},
|
|
409
437
|
|
|
410
|
-
/**
|
|
411
|
-
* @deprecated
|
|
412
|
-
*/
|
|
413
|
-
unmountAndReleaseReactRootNode: function() {
|
|
414
|
-
if ("production" !== process.env.NODE_ENV) {
|
|
415
|
-
console.warn(
|
|
416
|
-
'unmountAndReleaseReactRootNode() has been renamed to ' +
|
|
417
|
-
'unmountComponentAtNode() and will be removed in the next ' +
|
|
418
|
-
'version of React.'
|
|
419
|
-
);
|
|
420
|
-
}
|
|
421
|
-
return ReactMount.unmountComponentAtNode.apply(this, arguments);
|
|
422
|
-
},
|
|
423
|
-
|
|
424
438
|
/**
|
|
425
439
|
* Unmounts a component and removes it from the DOM.
|
|
426
440
|
*
|
|
@@ -533,39 +547,47 @@ var ReactMount = {
|
|
|
533
547
|
},
|
|
534
548
|
|
|
535
549
|
/**
|
|
536
|
-
* Finds a node with the supplied `
|
|
537
|
-
* Exploits the ID naming scheme to perform the search
|
|
550
|
+
* Finds a node with the supplied `targetID` inside of the supplied
|
|
551
|
+
* `ancestorNode`. Exploits the ID naming scheme to perform the search
|
|
552
|
+
* quickly.
|
|
538
553
|
*
|
|
539
554
|
* @param {DOMEventTarget} ancestorNode Search from this root.
|
|
540
|
-
* @pararm {string}
|
|
541
|
-
* @return {DOMEventTarget} DOM node with the supplied `
|
|
555
|
+
* @pararm {string} targetID ID of the DOM representation of the component.
|
|
556
|
+
* @return {DOMEventTarget} DOM node with the supplied `targetID`.
|
|
542
557
|
* @internal
|
|
543
558
|
*/
|
|
544
|
-
findComponentRoot: function(ancestorNode,
|
|
545
|
-
var firstChildren =
|
|
559
|
+
findComponentRoot: function(ancestorNode, targetID) {
|
|
560
|
+
var firstChildren = findComponentRootReusableArray;
|
|
546
561
|
var childIndex = 0;
|
|
547
562
|
|
|
563
|
+
var deepestAncestor = findDeepestCachedAncestor(targetID) || ancestorNode;
|
|
564
|
+
|
|
565
|
+
firstChildren[0] = deepestAncestor.firstChild;
|
|
566
|
+
firstChildren.length = 1;
|
|
567
|
+
|
|
548
568
|
while (childIndex < firstChildren.length) {
|
|
549
569
|
var child = firstChildren[childIndex++];
|
|
570
|
+
var targetChild;
|
|
571
|
+
|
|
550
572
|
while (child) {
|
|
551
573
|
var childID = ReactMount.getID(child);
|
|
552
574
|
if (childID) {
|
|
553
|
-
if
|
|
554
|
-
|
|
555
|
-
|
|
575
|
+
// Even if we find the node we're looking for, we finish looping
|
|
576
|
+
// through its siblings to ensure they're cached so that we don't have
|
|
577
|
+
// to revisit this node again. Otherwise, we make n^2 calls to getID
|
|
578
|
+
// when visiting the many children of a single node in order.
|
|
579
|
+
|
|
580
|
+
if (targetID === childID) {
|
|
581
|
+
targetChild = child;
|
|
582
|
+
} else if (ReactInstanceHandles.isAncestorIDOf(childID, targetID)) {
|
|
556
583
|
// If we find a child whose ID is an ancestor of the given ID,
|
|
557
584
|
// then we can be sure that we only want to search the subtree
|
|
558
585
|
// rooted at this child, so we can throw out the rest of the
|
|
559
586
|
// search state.
|
|
560
587
|
firstChildren.length = childIndex = 0;
|
|
561
588
|
firstChildren.push(child.firstChild);
|
|
562
|
-
break;
|
|
563
|
-
} else {
|
|
564
|
-
// TODO This should not be necessary if the ID hierarchy is
|
|
565
|
-
// correct, but is occasionally necessary if the DOM has been
|
|
566
|
-
// modified in unexpected ways.
|
|
567
|
-
firstChildren.push(child.firstChild);
|
|
568
589
|
}
|
|
590
|
+
|
|
569
591
|
} else {
|
|
570
592
|
// If this child had no ID, then there's a chance that it was
|
|
571
593
|
// injected automatically by the browser, as when a `<table>`
|
|
@@ -574,22 +596,28 @@ var ReactMount = {
|
|
|
574
596
|
// branch, but not before examining the other siblings.
|
|
575
597
|
firstChildren.push(child.firstChild);
|
|
576
598
|
}
|
|
599
|
+
|
|
577
600
|
child = child.nextSibling;
|
|
578
601
|
}
|
|
579
|
-
}
|
|
580
602
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
603
|
+
if (targetChild) {
|
|
604
|
+
// Emptying firstChildren/findComponentRootReusableArray is
|
|
605
|
+
// not necessary for correctness, but it helps the GC reclaim
|
|
606
|
+
// any nodes that were left at the end of the search.
|
|
607
|
+
firstChildren.length = 0;
|
|
608
|
+
|
|
609
|
+
return targetChild;
|
|
610
|
+
}
|
|
587
611
|
}
|
|
612
|
+
|
|
613
|
+
firstChildren.length = 0;
|
|
614
|
+
|
|
588
615
|
("production" !== process.env.NODE_ENV ? invariant(
|
|
589
616
|
false,
|
|
590
617
|
'findComponentRoot(..., %s): Unable to find element. This probably ' +
|
|
591
|
-
'means the DOM was unexpectedly mutated (e.g
|
|
592
|
-
|
|
618
|
+
'means the DOM was unexpectedly mutated (e.g., by the browser). ' +
|
|
619
|
+
'Try inspecting the child nodes of the element with React ID `%s`.',
|
|
620
|
+
targetID,
|
|
593
621
|
ReactMount.getID(ancestorNode)
|
|
594
622
|
) : invariant(false));
|
|
595
623
|
},
|
|
@@ -599,8 +627,6 @@ var ReactMount = {
|
|
|
599
627
|
* React ID utilities.
|
|
600
628
|
*/
|
|
601
629
|
|
|
602
|
-
ATTR_NAME: ATTR_NAME,
|
|
603
|
-
|
|
604
630
|
getReactRootID: getReactRootID,
|
|
605
631
|
|
|
606
632
|
getID: getID,
|
|
@@ -609,9 +635,7 @@ var ReactMount = {
|
|
|
609
635
|
|
|
610
636
|
getNode: getNode,
|
|
611
637
|
|
|
612
|
-
purgeID: purgeID
|
|
613
|
-
|
|
614
|
-
injection: {}
|
|
638
|
+
purgeID: purgeID
|
|
615
639
|
};
|
|
616
640
|
|
|
617
641
|
module.exports = ReactMount;
|