react 0.8.0 → 0.10.0
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 +32 -0
- package/lib/CSSCore.js +23 -22
- package/lib/CSSProperty.js +32 -1
- package/lib/CSSPropertyOperations.js +1 -1
- package/lib/ChangeEventPlugin.js +27 -5
- package/lib/ClientReactRootIndex.js +30 -0
- package/lib/CompositionEventPlugin.js +58 -10
- package/lib/DOMChildrenOperations.js +39 -3
- package/lib/DOMProperty.js +9 -5
- package/lib/DOMPropertyOperations.js +21 -8
- package/lib/Danger.js +9 -8
- package/lib/DefaultDOMPropertyConfig.js +23 -14
- package/lib/DefaultEventPluginOrder.js +1 -1
- package/lib/EnterLeaveEventPlugin.js +38 -5
- package/lib/EventConstants.js +4 -1
- package/lib/EventListener.js +42 -34
- package/lib/EventPluginHub.js +118 -13
- package/lib/EventPluginRegistry.js +62 -18
- package/lib/EventPluginUtils.js +33 -4
- package/lib/EventPropagators.js +7 -43
- package/lib/ExecutionEnvironment.js +4 -1
- package/lib/LinkedStateMixin.js +1 -1
- package/lib/LinkedValueUtils.js +160 -0
- package/lib/MobileSafariClickEventPlugin.js +1 -1
- package/lib/PooledClass.js +7 -1
- package/lib/React.js +30 -4
- package/lib/ReactBrowserComponentMixin.js +42 -0
- package/lib/ReactCSSTransitionGroup.js +65 -0
- package/lib/{ReactTransitionableChild.js → ReactCSSTransitionGroupChild.js} +22 -36
- package/lib/ReactChildren.js +4 -4
- package/lib/ReactComponent.js +163 -83
- package/lib/ReactComponentBrowserEnvironment.js +55 -71
- package/lib/ReactCompositeComponent.js +686 -119
- package/lib/ReactContext.js +67 -0
- package/lib/ReactCurrentOwner.js +1 -1
- package/lib/ReactDOM.js +19 -6
- package/lib/ReactDOMButton.js +6 -1
- package/lib/ReactDOMComponent.js +66 -24
- package/lib/ReactDOMForm.js +13 -3
- package/lib/ReactDOMIDOperations.js +106 -61
- package/lib/ReactDOMImg.js +61 -0
- package/lib/ReactDOMInput.js +28 -15
- package/lib/ReactDOMOption.js +13 -8
- package/lib/ReactDOMSelect.js +38 -18
- package/lib/ReactDOMSelection.js +1 -1
- package/lib/ReactDOMTextarea.js +19 -11
- package/lib/ReactDefaultBatchingStrategy.js +1 -1
- package/lib/ReactDefaultInjection.js +60 -26
- package/lib/ReactDefaultPerf.js +208 -371
- package/lib/ReactDefaultPerfAnalysis.js +199 -0
- package/lib/ReactErrorUtils.js +6 -15
- package/lib/ReactEventEmitter.js +144 -146
- package/lib/ReactEventEmitterMixin.js +1 -33
- package/lib/ReactEventTopLevelCallback.js +75 -15
- package/lib/ReactInjection.js +43 -0
- package/lib/ReactInputSelection.js +3 -2
- package/lib/ReactInstanceHandles.js +36 -20
- package/lib/ReactLink.js +2 -2
- package/lib/ReactMarkupChecksum.js +1 -1
- package/lib/ReactMount.js +136 -104
- package/lib/ReactMountReady.js +2 -2
- package/lib/ReactMultiChild.js +40 -49
- package/lib/ReactMultiChildUpdateTypes.js +3 -1
- package/lib/ReactOwner.js +17 -4
- package/lib/ReactPerf.js +6 -9
- package/lib/ReactPropTransferer.js +41 -22
- package/lib/ReactPropTypeLocationNames.js +31 -0
- package/lib/{ReactComponentEnvironment.js → ReactPropTypeLocations.js} +11 -6
- package/lib/ReactPropTypes.js +249 -48
- package/lib/ReactPutListenerQueue.js +61 -0
- package/lib/ReactReconcileTransaction.js +28 -7
- package/lib/ReactRootIndex.js +36 -0
- package/lib/ReactServerRendering.js +46 -19
- package/lib/ReactServerRenderingTransaction.js +116 -0
- package/lib/ReactStateSetters.js +1 -1
- package/lib/ReactTestUtils.js +394 -0
- package/lib/ReactTextComponent.js +33 -6
- package/lib/{ReactTransitionKeySet.js → ReactTransitionChildMapping.js} +43 -48
- package/lib/ReactTransitionEvents.js +1 -1
- package/lib/ReactTransitionGroup.js +133 -58
- package/lib/ReactUpdates.js +15 -12
- package/lib/ReactWithAddons.js +15 -3
- package/lib/SelectEventPlugin.js +23 -40
- package/lib/ServerReactRootIndex.js +36 -0
- package/lib/SimpleEventPlugin.js +55 -7
- package/lib/SyntheticClipboardEvent.js +8 -2
- package/lib/SyntheticCompositionEvent.js +1 -1
- package/lib/SyntheticDragEvent.js +44 -0
- package/lib/SyntheticEvent.js +3 -2
- package/lib/SyntheticFocusEvent.js +1 -1
- package/lib/SyntheticKeyboardEvent.js +5 -3
- package/lib/SyntheticMouseEvent.js +1 -1
- package/lib/SyntheticTouchEvent.js +1 -1
- package/lib/SyntheticUIEvent.js +1 -1
- package/lib/SyntheticWheelEvent.js +11 -8
- package/lib/Transaction.js +62 -37
- package/lib/ViewportMetrics.js +1 -1
- package/lib/accumulate.js +1 -1
- package/lib/adler32.js +1 -1
- package/lib/cloneWithProps.js +59 -0
- package/lib/containsNode.js +1 -1
- package/lib/copyProperties.js +1 -1
- package/lib/createArrayFrom.js +11 -14
- package/lib/createFullPageComponent.js +63 -0
- package/lib/createNodesFromMarkup.js +1 -1
- package/lib/createObjectFrom.js +1 -1
- package/lib/cx.js +3 -3
- package/lib/dangerousStyleValue.js +1 -1
- package/lib/emptyFunction.js +1 -1
- package/lib/emptyObject.js +27 -0
- package/lib/escapeTextForBrowser.js +1 -1
- package/lib/flattenChildren.js +6 -3
- package/lib/focusNode.js +33 -0
- package/lib/forEachAccumulated.js +1 -1
- package/lib/getActiveElement.js +5 -4
- package/lib/getEventKey.js +85 -0
- package/lib/getEventTarget.js +1 -1
- package/lib/getMarkupWrap.js +11 -1
- package/lib/getNodeForCharacterOffset.js +1 -1
- package/lib/getReactRootElementInContainer.js +1 -1
- package/lib/getTextContentAccessor.js +6 -4
- package/lib/getUnboundedScrollPosition.js +3 -3
- package/lib/hyphenate.js +1 -1
- package/lib/instantiateReactComponent.js +70 -0
- package/lib/invariant.js +20 -12
- package/lib/isEventSupported.js +8 -12
- package/lib/isNode.js +2 -2
- package/lib/isTextInputElement.js +1 -1
- package/lib/isTextNode.js +1 -1
- package/lib/joinClasses.js +1 -1
- package/lib/keyMirror.js +1 -1
- package/lib/keyOf.js +1 -1
- package/lib/memoizeStringOnly.js +1 -1
- package/lib/merge.js +1 -1
- package/lib/mergeHelpers.js +6 -7
- package/lib/mergeInto.js +1 -1
- package/lib/mixInto.js +1 -1
- package/lib/monitorCodeUse.js +37 -0
- package/lib/objMap.js +1 -1
- package/lib/objMapKeyVal.js +1 -1
- package/lib/onlyChild.js +43 -0
- package/lib/performanceNow.js +1 -1
- package/lib/shallowEqual.js +1 -1
- package/lib/shouldUpdateReactComponent.js +61 -0
- package/lib/toArray.js +75 -0
- package/lib/traverseAllChildren.js +72 -9
- package/lib/update.js +159 -0
- package/lib/warning.js +48 -0
- package/package.json +3 -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
package/lib/ReactDOMSelect.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright 2013 Facebook, Inc.
|
|
2
|
+
* Copyright 2013-2014 Facebook, Inc.
|
|
3
3
|
*
|
|
4
4
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
* you may not use this file except in compliance with the License.
|
|
@@ -18,7 +18,9 @@
|
|
|
18
18
|
|
|
19
19
|
"use strict";
|
|
20
20
|
|
|
21
|
-
var
|
|
21
|
+
var AutoFocusMixin = require("./AutoFocusMixin");
|
|
22
|
+
var LinkedValueUtils = require("./LinkedValueUtils");
|
|
23
|
+
var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin");
|
|
22
24
|
var ReactCompositeComponent = require("./ReactCompositeComponent");
|
|
23
25
|
var ReactDOM = require("./ReactDOM");
|
|
24
26
|
|
|
@@ -55,19 +57,28 @@ function selectValueType(props, propName, componentName) {
|
|
|
55
57
|
|
|
56
58
|
/**
|
|
57
59
|
* If `value` is supplied, updates <option> elements on mount and update.
|
|
60
|
+
* @param {ReactComponent} component Instance of ReactDOMSelect
|
|
61
|
+
* @param {?*} propValue For uncontrolled components, null/undefined. For
|
|
62
|
+
* controlled components, a string (or with `multiple`, a list of strings).
|
|
58
63
|
* @private
|
|
59
64
|
*/
|
|
60
|
-
function updateOptions() {
|
|
61
|
-
|
|
62
|
-
var
|
|
63
|
-
var
|
|
64
|
-
var
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
function updateOptions(component, propValue) {
|
|
66
|
+
var multiple = component.props.multiple;
|
|
67
|
+
var value = propValue != null ? propValue : component.state.value;
|
|
68
|
+
var options = component.getDOMNode().options;
|
|
69
|
+
var selectedValue, i, l;
|
|
70
|
+
if (multiple) {
|
|
71
|
+
selectedValue = {};
|
|
72
|
+
for (i = 0, l = value.length; i < l; ++i) {
|
|
73
|
+
selectedValue['' + value[i]] = true;
|
|
74
|
+
}
|
|
75
|
+
} else {
|
|
76
|
+
selectedValue = '' + value;
|
|
77
|
+
}
|
|
78
|
+
for (i = 0, l = options.length; i < l; i++) {
|
|
79
|
+
var selected = multiple ?
|
|
80
|
+
selectedValue.hasOwnProperty(options[i].value) :
|
|
81
|
+
options[i].value === selectedValue;
|
|
71
82
|
|
|
72
83
|
if (selected !== options[i].selected) {
|
|
73
84
|
options[i].selected = selected;
|
|
@@ -91,7 +102,9 @@ function updateOptions() {
|
|
|
91
102
|
* selected.
|
|
92
103
|
*/
|
|
93
104
|
var ReactDOMSelect = ReactCompositeComponent.createClass({
|
|
94
|
-
|
|
105
|
+
displayName: 'ReactDOMSelect',
|
|
106
|
+
|
|
107
|
+
mixins: [AutoFocusMixin, LinkedValueUtils.Mixin, ReactBrowserComponentMixin],
|
|
95
108
|
|
|
96
109
|
propTypes: {
|
|
97
110
|
defaultValue: selectValueType,
|
|
@@ -125,16 +138,23 @@ var ReactDOMSelect = ReactCompositeComponent.createClass({
|
|
|
125
138
|
return select(props, this.props.children);
|
|
126
139
|
},
|
|
127
140
|
|
|
128
|
-
componentDidMount:
|
|
141
|
+
componentDidMount: function() {
|
|
142
|
+
updateOptions(this, LinkedValueUtils.getValue(this));
|
|
143
|
+
},
|
|
129
144
|
|
|
130
|
-
componentDidUpdate:
|
|
145
|
+
componentDidUpdate: function() {
|
|
146
|
+
var value = LinkedValueUtils.getValue(this);
|
|
147
|
+
if (value != null) {
|
|
148
|
+
updateOptions(this, value);
|
|
149
|
+
}
|
|
150
|
+
},
|
|
131
151
|
|
|
132
152
|
_handleChange: function(event) {
|
|
133
153
|
var returnValue;
|
|
134
|
-
var onChange =
|
|
154
|
+
var onChange = LinkedValueUtils.getOnChange(this);
|
|
135
155
|
if (onChange) {
|
|
136
156
|
this._isChanging = true;
|
|
137
|
-
returnValue = onChange(event);
|
|
157
|
+
returnValue = onChange.call(this, event);
|
|
138
158
|
this._isChanging = false;
|
|
139
159
|
}
|
|
140
160
|
|
package/lib/ReactDOMSelection.js
CHANGED
package/lib/ReactDOMTextarea.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright 2013 Facebook, Inc.
|
|
2
|
+
* Copyright 2013-2014 Facebook, Inc.
|
|
3
3
|
*
|
|
4
4
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
* you may not use this file except in compliance with the License.
|
|
@@ -18,14 +18,18 @@
|
|
|
18
18
|
|
|
19
19
|
"use strict";
|
|
20
20
|
|
|
21
|
+
var AutoFocusMixin = require("./AutoFocusMixin");
|
|
21
22
|
var DOMPropertyOperations = require("./DOMPropertyOperations");
|
|
22
|
-
var
|
|
23
|
+
var LinkedValueUtils = require("./LinkedValueUtils");
|
|
24
|
+
var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin");
|
|
23
25
|
var ReactCompositeComponent = require("./ReactCompositeComponent");
|
|
24
26
|
var ReactDOM = require("./ReactDOM");
|
|
25
27
|
|
|
26
28
|
var invariant = require("./invariant");
|
|
27
29
|
var merge = require("./merge");
|
|
28
30
|
|
|
31
|
+
var warning = require("./warning");
|
|
32
|
+
|
|
29
33
|
// Store a reference to the <textarea> `ReactDOMComponent`.
|
|
30
34
|
var textarea = ReactDOM.textarea;
|
|
31
35
|
|
|
@@ -45,7 +49,9 @@ var textarea = ReactDOM.textarea;
|
|
|
45
49
|
* `defaultValue` if specified, or the children content (deprecated).
|
|
46
50
|
*/
|
|
47
51
|
var ReactDOMTextarea = ReactCompositeComponent.createClass({
|
|
48
|
-
|
|
52
|
+
displayName: 'ReactDOMTextarea',
|
|
53
|
+
|
|
54
|
+
mixins: [AutoFocusMixin, LinkedValueUtils.Mixin, ReactBrowserComponentMixin],
|
|
49
55
|
|
|
50
56
|
getInitialState: function() {
|
|
51
57
|
var defaultValue = this.props.defaultValue;
|
|
@@ -53,10 +59,11 @@ var ReactDOMTextarea = ReactCompositeComponent.createClass({
|
|
|
53
59
|
var children = this.props.children;
|
|
54
60
|
if (children != null) {
|
|
55
61
|
if ("production" !== process.env.NODE_ENV) {
|
|
56
|
-
|
|
62
|
+
("production" !== process.env.NODE_ENV ? warning(
|
|
63
|
+
false,
|
|
57
64
|
'Use the `defaultValue` or `value` props instead of setting ' +
|
|
58
65
|
'children on <textarea>.'
|
|
59
|
-
);
|
|
66
|
+
) : null);
|
|
60
67
|
}
|
|
61
68
|
("production" !== process.env.NODE_ENV ? invariant(
|
|
62
69
|
defaultValue == null,
|
|
@@ -75,7 +82,7 @@ var ReactDOMTextarea = ReactCompositeComponent.createClass({
|
|
|
75
82
|
if (defaultValue == null) {
|
|
76
83
|
defaultValue = '';
|
|
77
84
|
}
|
|
78
|
-
var value =
|
|
85
|
+
var value = LinkedValueUtils.getValue(this);
|
|
79
86
|
return {
|
|
80
87
|
// We save the initial value so that `ReactDOMComponent` doesn't update
|
|
81
88
|
// `textContent` (unnecessary since we update value).
|
|
@@ -94,7 +101,7 @@ var ReactDOMTextarea = ReactCompositeComponent.createClass({
|
|
|
94
101
|
render: function() {
|
|
95
102
|
// Clone `this.props` so we don't mutate the input.
|
|
96
103
|
var props = merge(this.props);
|
|
97
|
-
var value =
|
|
104
|
+
var value = LinkedValueUtils.getValue(this);
|
|
98
105
|
|
|
99
106
|
("production" !== process.env.NODE_ENV ? invariant(
|
|
100
107
|
props.dangerouslySetInnerHTML == null,
|
|
@@ -110,9 +117,10 @@ var ReactDOMTextarea = ReactCompositeComponent.createClass({
|
|
|
110
117
|
return textarea(props, this.state.initialValue);
|
|
111
118
|
},
|
|
112
119
|
|
|
113
|
-
componentDidUpdate: function(prevProps, prevState,
|
|
114
|
-
var value =
|
|
120
|
+
componentDidUpdate: function(prevProps, prevState, prevContext) {
|
|
121
|
+
var value = LinkedValueUtils.getValue(this);
|
|
115
122
|
if (value != null) {
|
|
123
|
+
var rootNode = this.getDOMNode();
|
|
116
124
|
// Cast `value` to a string to ensure the value is set correctly. While
|
|
117
125
|
// browsers typically do this as necessary, jsdom doesn't.
|
|
118
126
|
DOMPropertyOperations.setValueForProperty(rootNode, 'value', '' + value);
|
|
@@ -121,10 +129,10 @@ var ReactDOMTextarea = ReactCompositeComponent.createClass({
|
|
|
121
129
|
|
|
122
130
|
_handleChange: function(event) {
|
|
123
131
|
var returnValue;
|
|
124
|
-
var onChange =
|
|
132
|
+
var onChange = LinkedValueUtils.getOnChange(this);
|
|
125
133
|
if (onChange) {
|
|
126
134
|
this._isChanging = true;
|
|
127
|
-
returnValue = onChange(event);
|
|
135
|
+
returnValue = onChange.call(this, event);
|
|
128
136
|
this._isChanging = false;
|
|
129
137
|
}
|
|
130
138
|
this.setState({value: event.target.value});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright 2013 Facebook, Inc.
|
|
2
|
+
* Copyright 2013-2014 Facebook, Inc.
|
|
3
3
|
*
|
|
4
4
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
* you may not use this file except in compliance with the License.
|
|
@@ -18,46 +18,57 @@
|
|
|
18
18
|
|
|
19
19
|
"use strict";
|
|
20
20
|
|
|
21
|
-
var
|
|
22
|
-
|
|
23
|
-
var
|
|
24
|
-
var ReactDOMInput = require("./ReactDOMInput");
|
|
25
|
-
var ReactDOMOption = require("./ReactDOMOption");
|
|
26
|
-
var ReactDOMSelect = require("./ReactDOMSelect");
|
|
27
|
-
var ReactDOMTextarea = require("./ReactDOMTextarea");
|
|
28
|
-
var ReactEventEmitter = require("./ReactEventEmitter");
|
|
29
|
-
var ReactEventTopLevelCallback = require("./ReactEventTopLevelCallback");
|
|
30
|
-
var ReactPerf = require("./ReactPerf");
|
|
21
|
+
var ReactInjection = require("./ReactInjection");
|
|
22
|
+
|
|
23
|
+
var ExecutionEnvironment = require("./ExecutionEnvironment");
|
|
31
24
|
|
|
32
25
|
var DefaultDOMPropertyConfig = require("./DefaultDOMPropertyConfig");
|
|
33
|
-
var DOMProperty = require("./DOMProperty");
|
|
34
26
|
|
|
35
27
|
var ChangeEventPlugin = require("./ChangeEventPlugin");
|
|
28
|
+
var ClientReactRootIndex = require("./ClientReactRootIndex");
|
|
36
29
|
var CompositionEventPlugin = require("./CompositionEventPlugin");
|
|
37
30
|
var DefaultEventPluginOrder = require("./DefaultEventPluginOrder");
|
|
38
31
|
var EnterLeaveEventPlugin = require("./EnterLeaveEventPlugin");
|
|
39
|
-
var EventPluginHub = require("./EventPluginHub");
|
|
40
32
|
var MobileSafariClickEventPlugin = require("./MobileSafariClickEventPlugin");
|
|
33
|
+
var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin");
|
|
34
|
+
var ReactComponentBrowserEnvironment =
|
|
35
|
+
require("./ReactComponentBrowserEnvironment");
|
|
36
|
+
var ReactEventTopLevelCallback = require("./ReactEventTopLevelCallback");
|
|
37
|
+
var ReactDOM = require("./ReactDOM");
|
|
38
|
+
var ReactDOMButton = require("./ReactDOMButton");
|
|
39
|
+
var ReactDOMForm = require("./ReactDOMForm");
|
|
40
|
+
var ReactDOMImg = require("./ReactDOMImg");
|
|
41
|
+
var ReactDOMInput = require("./ReactDOMInput");
|
|
42
|
+
var ReactDOMOption = require("./ReactDOMOption");
|
|
43
|
+
var ReactDOMSelect = require("./ReactDOMSelect");
|
|
44
|
+
var ReactDOMTextarea = require("./ReactDOMTextarea");
|
|
41
45
|
var ReactInstanceHandles = require("./ReactInstanceHandles");
|
|
46
|
+
var ReactMount = require("./ReactMount");
|
|
42
47
|
var SelectEventPlugin = require("./SelectEventPlugin");
|
|
48
|
+
var ServerReactRootIndex = require("./ServerReactRootIndex");
|
|
43
49
|
var SimpleEventPlugin = require("./SimpleEventPlugin");
|
|
44
50
|
|
|
45
51
|
var ReactDefaultBatchingStrategy = require("./ReactDefaultBatchingStrategy");
|
|
46
|
-
|
|
52
|
+
|
|
53
|
+
var createFullPageComponent = require("./createFullPageComponent");
|
|
47
54
|
|
|
48
55
|
function inject() {
|
|
49
|
-
|
|
56
|
+
ReactInjection.EventEmitter.injectTopLevelCallbackCreator(
|
|
57
|
+
ReactEventTopLevelCallback
|
|
58
|
+
);
|
|
59
|
+
|
|
50
60
|
/**
|
|
51
|
-
* Inject
|
|
61
|
+
* Inject modules for resolving DOM hierarchy and plugin ordering.
|
|
52
62
|
*/
|
|
53
|
-
EventPluginHub.
|
|
54
|
-
EventPluginHub.
|
|
63
|
+
ReactInjection.EventPluginHub.injectEventPluginOrder(DefaultEventPluginOrder);
|
|
64
|
+
ReactInjection.EventPluginHub.injectInstanceHandle(ReactInstanceHandles);
|
|
65
|
+
ReactInjection.EventPluginHub.injectMount(ReactMount);
|
|
55
66
|
|
|
56
67
|
/**
|
|
57
68
|
* Some important event plugins included by default (without having to require
|
|
58
69
|
* them).
|
|
59
70
|
*/
|
|
60
|
-
EventPluginHub.
|
|
71
|
+
ReactInjection.EventPluginHub.injectEventPluginsByName({
|
|
61
72
|
SimpleEventPlugin: SimpleEventPlugin,
|
|
62
73
|
EnterLeaveEventPlugin: EnterLeaveEventPlugin,
|
|
63
74
|
ChangeEventPlugin: ChangeEventPlugin,
|
|
@@ -66,24 +77,47 @@ function inject() {
|
|
|
66
77
|
SelectEventPlugin: SelectEventPlugin
|
|
67
78
|
});
|
|
68
79
|
|
|
69
|
-
|
|
80
|
+
ReactInjection.DOM.injectComponentClasses({
|
|
70
81
|
button: ReactDOMButton,
|
|
71
82
|
form: ReactDOMForm,
|
|
83
|
+
img: ReactDOMImg,
|
|
72
84
|
input: ReactDOMInput,
|
|
73
85
|
option: ReactDOMOption,
|
|
74
86
|
select: ReactDOMSelect,
|
|
75
|
-
textarea: ReactDOMTextarea
|
|
87
|
+
textarea: ReactDOMTextarea,
|
|
88
|
+
|
|
89
|
+
html: createFullPageComponent(ReactDOM.html),
|
|
90
|
+
head: createFullPageComponent(ReactDOM.head),
|
|
91
|
+
title: createFullPageComponent(ReactDOM.title),
|
|
92
|
+
body: createFullPageComponent(ReactDOM.body)
|
|
76
93
|
});
|
|
77
94
|
|
|
78
|
-
DOMProperty.injection.injectDOMPropertyConfig(DefaultDOMPropertyConfig);
|
|
79
95
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
96
|
+
// This needs to happen after createFullPageComponent() otherwise the mixin
|
|
97
|
+
// gets double injected.
|
|
98
|
+
ReactInjection.CompositeComponent.injectMixin(ReactBrowserComponentMixin);
|
|
83
99
|
|
|
84
|
-
|
|
100
|
+
ReactInjection.DOMProperty.injectDOMPropertyConfig(DefaultDOMPropertyConfig);
|
|
101
|
+
|
|
102
|
+
ReactInjection.Updates.injectBatchingStrategy(
|
|
85
103
|
ReactDefaultBatchingStrategy
|
|
86
104
|
);
|
|
105
|
+
|
|
106
|
+
ReactInjection.RootIndex.injectCreateReactRootIndex(
|
|
107
|
+
ExecutionEnvironment.canUseDOM ?
|
|
108
|
+
ClientReactRootIndex.createReactRootIndex :
|
|
109
|
+
ServerReactRootIndex.createReactRootIndex
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
ReactInjection.Component.injectEnvironment(ReactComponentBrowserEnvironment);
|
|
113
|
+
|
|
114
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
115
|
+
var url = (ExecutionEnvironment.canUseDOM && window.location.href) || '';
|
|
116
|
+
if ((/[?&]react_perf\b/).test(url)) {
|
|
117
|
+
var ReactDefaultPerf = require("./ReactDefaultPerf");
|
|
118
|
+
ReactDefaultPerf.start();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
87
121
|
}
|
|
88
122
|
|
|
89
123
|
module.exports = {
|
package/lib/ReactDefaultPerf.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright 2013 Facebook, Inc.
|
|
2
|
+
* Copyright 2013-2014 Facebook, Inc.
|
|
3
3
|
*
|
|
4
4
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
* you may not use this file except in compliance with the License.
|
|
@@ -19,389 +19,226 @@
|
|
|
19
19
|
|
|
20
20
|
"use strict";
|
|
21
21
|
|
|
22
|
+
var DOMProperty = require("./DOMProperty");
|
|
23
|
+
var ReactDefaultPerfAnalysis = require("./ReactDefaultPerfAnalysis");
|
|
24
|
+
var ReactMount = require("./ReactMount");
|
|
25
|
+
var ReactPerf = require("./ReactPerf");
|
|
26
|
+
|
|
22
27
|
var performanceNow = require("./performanceNow");
|
|
23
28
|
|
|
24
|
-
|
|
29
|
+
function roundFloat(val) {
|
|
30
|
+
return Math.floor(val * 100) / 100;
|
|
31
|
+
}
|
|
25
32
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
* Gets the stored information for a given object's function.
|
|
30
|
-
*
|
|
31
|
-
* @param {string} objName
|
|
32
|
-
* @param {string} fnName
|
|
33
|
-
* @return {?object}
|
|
34
|
-
*/
|
|
35
|
-
getInfo: function(objName, fnName) {
|
|
36
|
-
if (!this.info[objName] || !this.info[objName][fnName]) {
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
return this.info[objName][fnName];
|
|
40
|
-
},
|
|
33
|
+
var ReactDefaultPerf = {
|
|
34
|
+
_allMeasurements: [], // last item in the list is the current one
|
|
35
|
+
_injected: false,
|
|
41
36
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
* @param {string} fnName
|
|
47
|
-
* @return {?array<object>}
|
|
48
|
-
*/
|
|
49
|
-
getLogs: function(objName, fnName) {
|
|
50
|
-
if (!this.getInfo(objName, fnName)) {
|
|
51
|
-
return null;
|
|
52
|
-
}
|
|
53
|
-
return this.logs.filter(function(log) {
|
|
54
|
-
return log.objName === objName && log.fnName === fnName;
|
|
55
|
-
});
|
|
56
|
-
},
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Runs through the logs and builds an array of arrays, where each array
|
|
60
|
-
* walks through the mounting/updating of each component underneath.
|
|
61
|
-
*
|
|
62
|
-
* @param {string} rootID The reactID of the root node, e.g. '.r[2cpyq]'
|
|
63
|
-
* @return {array<array>}
|
|
64
|
-
*/
|
|
65
|
-
getRawRenderHistory: function(rootID) {
|
|
66
|
-
var history = [];
|
|
67
|
-
/**
|
|
68
|
-
* Since logs are added after the method returns, the logs are in a sense
|
|
69
|
-
* upside-down: the inner-most elements from mounting/updating are logged
|
|
70
|
-
* first, and the last addition to the log is the top renderComponent.
|
|
71
|
-
* Therefore, we flip the logs upside down for ease of processing, and
|
|
72
|
-
* reverse the history array at the end so the earliest event has index 0.
|
|
73
|
-
*/
|
|
74
|
-
var logs = this.logs.filter(function(log) {
|
|
75
|
-
return log.reactID.indexOf(rootID) === 0;
|
|
76
|
-
}).reverse();
|
|
37
|
+
start: function() {
|
|
38
|
+
if (!ReactDefaultPerf._injected) {
|
|
39
|
+
ReactPerf.injection.injectMeasure(ReactDefaultPerf.measure);
|
|
40
|
+
}
|
|
77
41
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
42
|
+
ReactDefaultPerf._allMeasurements.length = 0;
|
|
43
|
+
ReactPerf.enableMeasure = true;
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
stop: function() {
|
|
47
|
+
ReactPerf.enableMeasure = false;
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
getLastMeasurements: function() {
|
|
51
|
+
return ReactDefaultPerf._allMeasurements;
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
printExclusive: function(measurements) {
|
|
55
|
+
measurements = measurements || ReactDefaultPerf._allMeasurements;
|
|
56
|
+
var summary = ReactDefaultPerfAnalysis.getExclusiveSummary(measurements);
|
|
57
|
+
console.table(summary.map(function(item) {
|
|
58
|
+
return {
|
|
59
|
+
'Component class name': item.componentName,
|
|
60
|
+
'Total inclusive time (ms)': roundFloat(item.inclusive),
|
|
61
|
+
'Total exclusive time (ms)': roundFloat(item.exclusive),
|
|
62
|
+
'Exclusive time per instance (ms)': roundFloat(item.exclusive / item.count),
|
|
63
|
+
'Instances': item.count
|
|
64
|
+
};
|
|
65
|
+
}));
|
|
66
|
+
console.log(
|
|
67
|
+
'Total time:',
|
|
68
|
+
ReactDefaultPerfAnalysis.getTotalTime(measurements).toFixed(2) + ' ms'
|
|
69
|
+
);
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
printInclusive: function(measurements) {
|
|
73
|
+
measurements = measurements || ReactDefaultPerf._allMeasurements;
|
|
74
|
+
var summary = ReactDefaultPerfAnalysis.getInclusiveSummary(measurements);
|
|
75
|
+
console.table(summary.map(function(item) {
|
|
76
|
+
return {
|
|
77
|
+
'Owner > component': item.componentName,
|
|
78
|
+
'Inclusive time (ms)': roundFloat(item.time),
|
|
79
|
+
'Instances': item.count
|
|
80
|
+
};
|
|
81
|
+
}));
|
|
82
|
+
console.log(
|
|
83
|
+
'Total time:',
|
|
84
|
+
ReactDefaultPerfAnalysis.getTotalTime(measurements).toFixed(2) + ' ms'
|
|
85
|
+
);
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
printWasted: function(measurements) {
|
|
89
|
+
measurements = measurements || ReactDefaultPerf._allMeasurements;
|
|
90
|
+
var summary = ReactDefaultPerfAnalysis.getInclusiveSummary(
|
|
91
|
+
measurements,
|
|
92
|
+
true
|
|
93
|
+
);
|
|
94
|
+
console.table(summary.map(function(item) {
|
|
95
|
+
return {
|
|
96
|
+
'Owner > component': item.componentName,
|
|
97
|
+
'Wasted time (ms)': item.time,
|
|
98
|
+
'Instances': item.count
|
|
99
|
+
};
|
|
100
|
+
}));
|
|
101
|
+
console.log(
|
|
102
|
+
'Total time:',
|
|
103
|
+
ReactDefaultPerfAnalysis.getTotalTime(measurements).toFixed(2) + ' ms'
|
|
104
|
+
);
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
printDOM: function(measurements) {
|
|
108
|
+
measurements = measurements || ReactDefaultPerf._allMeasurements;
|
|
109
|
+
var summary = ReactDefaultPerfAnalysis.getDOMSummary(measurements);
|
|
110
|
+
console.table(summary.map(function(item) {
|
|
111
|
+
var result = {};
|
|
112
|
+
result[DOMProperty.ID_ATTRIBUTE_NAME] = item.id;
|
|
113
|
+
result['type'] = item.type;
|
|
114
|
+
result['args'] = JSON.stringify(item.args);
|
|
115
|
+
return result;
|
|
116
|
+
}));
|
|
117
|
+
console.log(
|
|
118
|
+
'Total time:',
|
|
119
|
+
ReactDefaultPerfAnalysis.getTotalTime(measurements).toFixed(2) + ' ms'
|
|
120
|
+
);
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
_recordWrite: function(id, fnName, totalTime, args) {
|
|
124
|
+
// TODO: totalTime isn't that useful since it doesn't count paints/reflows
|
|
125
|
+
var writes =
|
|
126
|
+
ReactDefaultPerf
|
|
127
|
+
._allMeasurements[ReactDefaultPerf._allMeasurements.length - 1]
|
|
128
|
+
.writes;
|
|
129
|
+
writes[id] = writes[id] || [];
|
|
130
|
+
writes[id].push({
|
|
131
|
+
type: fnName,
|
|
132
|
+
time: totalTime,
|
|
133
|
+
args: args
|
|
134
|
+
});
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
measure: function(moduleName, fnName, func) {
|
|
138
|
+
return function() {var args=Array.prototype.slice.call(arguments,0);
|
|
139
|
+
var totalTime;
|
|
140
|
+
var rv;
|
|
141
|
+
var start;
|
|
142
|
+
|
|
143
|
+
if (fnName === '_renderNewRootComponent' ||
|
|
144
|
+
fnName === 'flushBatchedUpdates') {
|
|
145
|
+
// A "measurement" is a set of metrics recorded for each flush. We want
|
|
146
|
+
// to group the metrics for a given flush together so we can look at the
|
|
147
|
+
// components that rendered and the DOM operations that actually
|
|
148
|
+
// happened to determine the amount of "wasted work" performed.
|
|
149
|
+
ReactDefaultPerf._allMeasurements.push({
|
|
150
|
+
exclusive: {},
|
|
151
|
+
inclusive: {},
|
|
152
|
+
counts: {},
|
|
153
|
+
writes: {},
|
|
154
|
+
displayNames: {},
|
|
155
|
+
totalTime: 0
|
|
156
|
+
});
|
|
157
|
+
start = performanceNow();
|
|
158
|
+
rv = func.apply(this, args);
|
|
159
|
+
ReactDefaultPerf._allMeasurements[
|
|
160
|
+
ReactDefaultPerf._allMeasurements.length - 1
|
|
161
|
+
].totalTime = performanceNow() - start;
|
|
162
|
+
return rv;
|
|
163
|
+
} else if (moduleName === 'ReactDOMIDOperations' ||
|
|
164
|
+
moduleName === 'ReactComponentBrowserEnvironment') {
|
|
165
|
+
start = performanceNow();
|
|
166
|
+
rv = func.apply(this, args);
|
|
167
|
+
totalTime = performanceNow() - start;
|
|
168
|
+
|
|
169
|
+
if (fnName === 'mountImageIntoNode') {
|
|
170
|
+
var mountID = ReactMount.getID(args[1]);
|
|
171
|
+
ReactDefaultPerf._recordWrite(mountID, fnName, totalTime, args[0]);
|
|
172
|
+
} else if (fnName === 'dangerouslyProcessChildrenUpdates') {
|
|
173
|
+
// special format
|
|
174
|
+
args[0].forEach(function(update) {
|
|
175
|
+
var writeArgs = {};
|
|
176
|
+
if (update.fromIndex !== null) {
|
|
177
|
+
writeArgs.fromIndex = update.fromIndex;
|
|
178
|
+
}
|
|
179
|
+
if (update.toIndex !== null) {
|
|
180
|
+
writeArgs.toIndex = update.toIndex;
|
|
181
|
+
}
|
|
182
|
+
if (update.textContent !== null) {
|
|
183
|
+
writeArgs.textContent = update.textContent;
|
|
184
|
+
}
|
|
185
|
+
if (update.markupIndex !== null) {
|
|
186
|
+
writeArgs.markup = args[1][update.markupIndex];
|
|
187
|
+
}
|
|
188
|
+
ReactDefaultPerf._recordWrite(
|
|
189
|
+
update.parentID,
|
|
190
|
+
update.type,
|
|
191
|
+
totalTime,
|
|
192
|
+
writeArgs
|
|
193
|
+
);
|
|
194
|
+
});
|
|
195
|
+
} else {
|
|
196
|
+
// basic format
|
|
197
|
+
ReactDefaultPerf._recordWrite(
|
|
198
|
+
args[0],
|
|
199
|
+
fnName,
|
|
200
|
+
totalTime,
|
|
201
|
+
Array.prototype.slice.call(args, 1)
|
|
202
|
+
);
|
|
83
203
|
}
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
var history = this.getRawRenderHistory(rootID);
|
|
102
|
-
|
|
103
|
-
return history.map(function(subHistory) {
|
|
104
|
-
var headerString = (
|
|
105
|
-
'log# Component (execution time) [bloat from logging]\n' +
|
|
106
|
-
'================================================================\n'
|
|
107
|
-
);
|
|
108
|
-
return headerString + subHistory.map(function(log) {
|
|
109
|
-
// Add two spaces for every layer in the reactID.
|
|
110
|
-
var indents = '\t' + Array(log.reactID.split('.[').length).join(' ');
|
|
111
|
-
var delta = _microTime(log.timing.delta);
|
|
112
|
-
var bloat = _microTime(log.timing.timeToLog);
|
|
113
|
-
|
|
114
|
-
return log.index + indents + log.name + ' (' + delta + 'ms)' +
|
|
115
|
-
' [' + bloat + 'ms]';
|
|
116
|
-
}).join('\n');
|
|
117
|
-
});
|
|
118
|
-
},
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Print the render history from `getRenderHistory` using console.log.
|
|
122
|
-
* This is currently the best way to display perf data from
|
|
123
|
-
* any React component; working on that.
|
|
124
|
-
*
|
|
125
|
-
* @param {string} rootID The reactID of the root node, e.g. '.r[2cpyq]'
|
|
126
|
-
* @param {number} index
|
|
127
|
-
*/
|
|
128
|
-
printRenderHistory: function(rootID, index) {
|
|
129
|
-
var history = this.getRenderHistory(rootID);
|
|
130
|
-
if (!history[index]) {
|
|
131
|
-
console.warn(
|
|
132
|
-
'Index', index, 'isn\'t available! ' +
|
|
133
|
-
'The render history is', history.length, 'long.'
|
|
134
|
-
);
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
console.log(
|
|
138
|
-
'Loading render history #' + (index + 1) +
|
|
139
|
-
' of ' + history.length + ':\n' + history[index]
|
|
140
|
-
);
|
|
141
|
-
},
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Prints the heatmap legend to console, showing how the colors correspond
|
|
145
|
-
* with render times. This relies on console.log styles.
|
|
146
|
-
*/
|
|
147
|
-
printHeatmapLegend: function() {
|
|
148
|
-
if (!this.options.heatmap.enabled) {
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
var max = this.info.React
|
|
152
|
-
&& this.info.React.renderComponent
|
|
153
|
-
&& this.info.React.renderComponent.max;
|
|
154
|
-
if (max) {
|
|
155
|
-
var logStr = 'Heatmap: ';
|
|
156
|
-
for (var ii = 0; ii <= 10 * max; ii += max) {
|
|
157
|
-
logStr += '%c ' + (Math.round(ii) / 10) + 'ms ';
|
|
204
|
+
return rv;
|
|
205
|
+
} else if (moduleName === 'ReactCompositeComponent' && (
|
|
206
|
+
fnName === 'mountComponent' ||
|
|
207
|
+
fnName === 'updateComponent' || // TODO: receiveComponent()?
|
|
208
|
+
fnName === '_renderValidatedComponent')) {
|
|
209
|
+
|
|
210
|
+
var rootNodeID = fnName === 'mountComponent' ?
|
|
211
|
+
args[0] :
|
|
212
|
+
this._rootNodeID;
|
|
213
|
+
var isRender = fnName === '_renderValidatedComponent';
|
|
214
|
+
var entry = ReactDefaultPerf._allMeasurements[
|
|
215
|
+
ReactDefaultPerf._allMeasurements.length - 1
|
|
216
|
+
];
|
|
217
|
+
|
|
218
|
+
if (isRender) {
|
|
219
|
+
entry.counts[rootNodeID] = entry.counts[rootNodeID] || 0;
|
|
220
|
+
entry.counts[rootNodeID] += 1;
|
|
158
221
|
}
|
|
159
|
-
console.log(
|
|
160
|
-
logStr,
|
|
161
|
-
'background-color: hsla(100, 100%, 50%, 0.6);',
|
|
162
|
-
'background-color: hsla( 90, 100%, 50%, 0.6);',
|
|
163
|
-
'background-color: hsla( 80, 100%, 50%, 0.6);',
|
|
164
|
-
'background-color: hsla( 70, 100%, 50%, 0.6);',
|
|
165
|
-
'background-color: hsla( 60, 100%, 50%, 0.6);',
|
|
166
|
-
'background-color: hsla( 50, 100%, 50%, 0.6);',
|
|
167
|
-
'background-color: hsla( 40, 100%, 50%, 0.6);',
|
|
168
|
-
'background-color: hsla( 30, 100%, 50%, 0.6);',
|
|
169
|
-
'background-color: hsla( 20, 100%, 50%, 0.6);',
|
|
170
|
-
'background-color: hsla( 10, 100%, 50%, 0.6);',
|
|
171
|
-
'background-color: hsla( 0, 100%, 50%, 0.6);'
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
},
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Measure a given function with logging information, and calls a callback
|
|
178
|
-
* if there is one.
|
|
179
|
-
*
|
|
180
|
-
* @param {string} objName
|
|
181
|
-
* @param {string} fnName
|
|
182
|
-
* @param {function} func
|
|
183
|
-
* @return {function}
|
|
184
|
-
*/
|
|
185
|
-
measure: function(objName, fnName, func) {
|
|
186
|
-
var info = _getNewInfo(objName, fnName);
|
|
187
222
|
|
|
188
|
-
|
|
223
|
+
start = performanceNow();
|
|
224
|
+
rv = func.apply(this, args);
|
|
225
|
+
totalTime = performanceNow() - start;
|
|
189
226
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
var timeAfterFn = performanceNow();
|
|
227
|
+
var typeOfLog = isRender ? entry.exclusive : entry.inclusive;
|
|
228
|
+
typeOfLog[rootNodeID] = typeOfLog[rootNodeID] || 0;
|
|
229
|
+
typeOfLog[rootNodeID] += totalTime;
|
|
194
230
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
* argument in the log, do so in the callback.
|
|
199
|
-
*/
|
|
200
|
-
var args = {};
|
|
201
|
-
for (var i = 0; i < arguments.length; i++) {
|
|
202
|
-
args[fnArgs[i]] = arguments[i];
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
var log = {
|
|
206
|
-
index: ReactDefaultPerf.logs.length,
|
|
207
|
-
fnName: fnName,
|
|
208
|
-
objName: objName,
|
|
209
|
-
timing: {
|
|
210
|
-
before: timeBeforeFn,
|
|
211
|
-
after: timeAfterFn,
|
|
212
|
-
delta: timeAfterFn - timeBeforeFn
|
|
213
|
-
}
|
|
231
|
+
entry.displayNames[rootNodeID] = {
|
|
232
|
+
current: this.constructor.displayName,
|
|
233
|
+
owner: this._owner ? this._owner.constructor.displayName : '<root>'
|
|
214
234
|
};
|
|
215
235
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* The callback gets:
|
|
220
|
-
* - this (the component)
|
|
221
|
-
* - the original method's arguments
|
|
222
|
-
* - what the method returned
|
|
223
|
-
* - the log object, and
|
|
224
|
-
* - the wrapped method's info object.
|
|
225
|
-
*/
|
|
226
|
-
var callback = _getCallback(objName, fnName);
|
|
227
|
-
callback && callback(this, args, fnReturn, log, info);
|
|
228
|
-
|
|
229
|
-
log.timing.timeToLog = performanceNow() - timeAfterFn;
|
|
230
|
-
|
|
231
|
-
return fnReturn;
|
|
232
|
-
};
|
|
233
|
-
},
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Holds information on wrapped objects/methods.
|
|
237
|
-
* For instance, ReactDefaultPerf.info.React.renderComponent
|
|
238
|
-
*/
|
|
239
|
-
info: {},
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Holds all of the logs. Filter this to pull desired information.
|
|
243
|
-
*/
|
|
244
|
-
logs: [],
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* Toggle settings for ReactDefaultPerf
|
|
248
|
-
*/
|
|
249
|
-
options: {
|
|
250
|
-
/**
|
|
251
|
-
* The heatmap sets the background color of the React containers
|
|
252
|
-
* according to how much total time has been spent rendering them.
|
|
253
|
-
* The most temporally expensive component is set as pure red,
|
|
254
|
-
* and the others are colored from green to red as a fraction
|
|
255
|
-
* of that max component time.
|
|
256
|
-
*/
|
|
257
|
-
heatmap: {
|
|
258
|
-
enabled: true
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
};
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Gets a info area for a given object's function, adding a new one if
|
|
265
|
-
* necessary.
|
|
266
|
-
*
|
|
267
|
-
* @param {string} objName
|
|
268
|
-
* @param {string} fnName
|
|
269
|
-
* @return {object}
|
|
270
|
-
*/
|
|
271
|
-
var _getNewInfo = function(objName, fnName) {
|
|
272
|
-
var info = ReactDefaultPerf.getInfo(objName, fnName);
|
|
273
|
-
if (info) {
|
|
274
|
-
return info;
|
|
275
|
-
}
|
|
276
|
-
ReactDefaultPerf.info[objName] = ReactDefaultPerf.info[objName] || {};
|
|
277
|
-
|
|
278
|
-
return ReactDefaultPerf.info[objName][fnName] = {
|
|
279
|
-
getLogs: function() {
|
|
280
|
-
return ReactDefaultPerf.getLogs(objName, fnName);
|
|
281
|
-
}
|
|
282
|
-
};
|
|
283
|
-
};
|
|
284
|
-
|
|
285
|
-
/**
|
|
286
|
-
* Gets a list of the argument names from a function's definition.
|
|
287
|
-
* This is useful for storing arguments by their names within wrapFn().
|
|
288
|
-
*
|
|
289
|
-
* @param {function} fn
|
|
290
|
-
* @return {array<string>}
|
|
291
|
-
*/
|
|
292
|
-
var _getFnArguments = function(fn) {
|
|
293
|
-
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
|
|
294
|
-
var fnStr = fn.toString().replace(STRIP_COMMENTS, '');
|
|
295
|
-
fnStr = fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')'));
|
|
296
|
-
return fnStr.match(/([^\s,]+)/g);
|
|
297
|
-
};
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Store common callbacks within ReactDefaultPerf.
|
|
301
|
-
*
|
|
302
|
-
* @param {string} objName
|
|
303
|
-
* @param {string} fnName
|
|
304
|
-
* @return {?function}
|
|
305
|
-
*/
|
|
306
|
-
var _getCallback = function(objName, fnName) {
|
|
307
|
-
switch (objName + '.' + fnName) {
|
|
308
|
-
case 'React.renderComponent':
|
|
309
|
-
return _renderComponentCallback;
|
|
310
|
-
case 'ReactDOMComponent.mountComponent':
|
|
311
|
-
case 'ReactDOMComponent.updateComponent':
|
|
312
|
-
return _nativeComponentCallback;
|
|
313
|
-
case 'ReactCompositeComponent.mountComponent':
|
|
314
|
-
case 'ReactCompositeComponent.updateComponent':
|
|
315
|
-
return _compositeComponentCallback;
|
|
316
|
-
default:
|
|
317
|
-
return null;
|
|
318
|
-
}
|
|
319
|
-
};
|
|
320
|
-
|
|
321
|
-
/**
|
|
322
|
-
* Callback function for React.renderComponent
|
|
323
|
-
*
|
|
324
|
-
* @param {object} component
|
|
325
|
-
* @param {object} args
|
|
326
|
-
* @param {?object} fnReturn
|
|
327
|
-
* @param {object} log
|
|
328
|
-
* @param {object} info
|
|
329
|
-
*/
|
|
330
|
-
var _renderComponentCallback =
|
|
331
|
-
function(component, args, fnReturn, log, info) {
|
|
332
|
-
log.name = args.nextComponent.constructor.displayName || '[unknown]';
|
|
333
|
-
log.reactID = fnReturn._rootNodeID || null;
|
|
334
|
-
|
|
335
|
-
if (ReactDefaultPerf.options.heatmap.enabled) {
|
|
336
|
-
var container = args.container;
|
|
337
|
-
if (!container.loggedByReactDefaultPerf) {
|
|
338
|
-
container.loggedByReactDefaultPerf = true;
|
|
339
|
-
info.components = info.components || [];
|
|
340
|
-
info.components.push(container);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
container.count = container.count || 0;
|
|
344
|
-
container.count += log.timing.delta;
|
|
345
|
-
info.max = info.max || 0;
|
|
346
|
-
if (container.count > info.max) {
|
|
347
|
-
info.max = container.count;
|
|
348
|
-
info.components.forEach(function(component) {
|
|
349
|
-
_setHue(component, 100 - 100 * component.count / info.max);
|
|
350
|
-
});
|
|
236
|
+
return rv;
|
|
351
237
|
} else {
|
|
352
|
-
|
|
238
|
+
return func.apply(this, args);
|
|
353
239
|
}
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
/**
|
|
358
|
-
* Callback function for ReactDOMComponent
|
|
359
|
-
*
|
|
360
|
-
* @param {object} component
|
|
361
|
-
* @param {object} args
|
|
362
|
-
* @param {?object} fnReturn
|
|
363
|
-
* @param {object} log
|
|
364
|
-
* @param {object} info
|
|
365
|
-
*/
|
|
366
|
-
var _nativeComponentCallback =
|
|
367
|
-
function(component, args, fnReturn, log, info) {
|
|
368
|
-
log.name = component.tagName || '[unknown]';
|
|
369
|
-
log.reactID = component._rootNodeID;
|
|
370
|
-
};
|
|
371
|
-
|
|
372
|
-
/**
|
|
373
|
-
* Callback function for ReactCompositeComponent
|
|
374
|
-
*
|
|
375
|
-
* @param {object} component
|
|
376
|
-
* @param {object} args
|
|
377
|
-
* @param {?object} fnReturn
|
|
378
|
-
* @param {object} log
|
|
379
|
-
* @param {object} info
|
|
380
|
-
*/
|
|
381
|
-
var _compositeComponentCallback =
|
|
382
|
-
function(component, args, fnReturn, log, info) {
|
|
383
|
-
log.name = component.constructor.displayName || '[unknown]';
|
|
384
|
-
log.reactID = component._rootNodeID;
|
|
385
|
-
};
|
|
386
|
-
|
|
387
|
-
/**
|
|
388
|
-
* Using the hsl() background-color attribute, colors an element.
|
|
389
|
-
*
|
|
390
|
-
* @param {DOMElement} el
|
|
391
|
-
* @param {number} hue [0 for red, 120 for green, 240 for blue]
|
|
392
|
-
*/
|
|
393
|
-
var _setHue = function(el, hue) {
|
|
394
|
-
el.style.backgroundColor = 'hsla(' + hue + ', 100%, 50%, 0.6)';
|
|
395
|
-
};
|
|
396
|
-
|
|
397
|
-
/**
|
|
398
|
-
* Round to the thousandth place.
|
|
399
|
-
* @param {number} time
|
|
400
|
-
* @return {number}
|
|
401
|
-
*/
|
|
402
|
-
var _microTime = function(time) {
|
|
403
|
-
return Math.round(time * 1000) / 1000;
|
|
404
|
-
};
|
|
405
|
-
}
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
};
|
|
406
243
|
|
|
407
244
|
module.exports = ReactDefaultPerf;
|