12
12
'use strict' ;
13
13
14
14
var invariant = require ( 'invariant' ) ;
15
+ var warning = require ( 'warning' ) ;
15
16
16
17
var tree = { } ;
17
18
var unmountedIDs = { } ;
18
19
var rootIDs = { } ;
19
20
21
+ var processingStack = [ ] ;
22
+
23
+ function startProcessing ( id ) {
24
+ processingStack . push ( id ) ;
25
+ }
26
+
27
+ function stopProcessing ( id ) {
28
+ // This should just be a single .pop() in most cases, but maybe not if there
29
+ // was an exception or similar.
30
+ do {
31
+ if ( ! processingStack . length ) {
32
+ warning (
33
+ false ,
34
+ 'ReactComponentTreeDevtool: stopProcessing(%s) called, no match found.' ,
35
+ id
36
+ ) ;
37
+ return ;
38
+ }
39
+ } while ( processingStack . pop ( ) !== id ) ;
40
+ }
41
+
20
42
function updateTree ( id , update ) {
21
43
if ( ! tree [ id ] ) {
22
44
tree [ id ] = {
@@ -96,15 +118,18 @@ var ReactComponentTreeDevtool = {
96
118
97
119
onBeforeMountComponent ( id , element ) {
98
120
updateTree ( id , item => item . element = element ) ;
121
+ startProcessing ( id ) ;
99
122
} ,
100
123
101
124
onBeforeUpdateComponent ( id , element ) {
102
125
updateTree ( id , item => item . element = element ) ;
126
+ startProcessing ( id ) ;
103
127
} ,
104
128
105
129
onMountComponent ( id ) {
106
130
updateTree ( id , item => item . isMounted = true ) ;
107
131
delete unmountedIDs [ id ] ;
132
+ stopProcessing ( id ) ;
108
133
} ,
109
134
110
135
onMountRootComponent ( id ) {
@@ -113,6 +138,7 @@ var ReactComponentTreeDevtool = {
113
138
114
139
onUpdateComponent ( id ) {
115
140
updateTree ( id , item => item . updateCount ++ ) ;
141
+ stopProcessing ( id ) ;
116
142
} ,
117
143
118
144
onUnmountComponent ( id ) {
@@ -138,6 +164,67 @@ var ReactComponentTreeDevtool = {
138
164
return item ? item . isMounted : false ;
139
165
} ,
140
166
167
+ getCurrentStackAddendum ( topElement ) {
168
+ function describeComponentFrame ( name , source , ownerName ) {
169
+ return '\n in ' + name + (
170
+ source ?
171
+ ' (at ' + source . fileName . replace ( / ^ .* [ \\ \/ ] / , '' ) + ':' +
172
+ source . lineNumber + ')' :
173
+ ownerName ?
174
+ ' (created by ' + ownerName + ')' :
175
+ ''
176
+ ) ;
177
+ }
178
+
179
+ function describeID ( id ) {
180
+ var name = ReactComponentTreeDevtool . getDisplayName ( id ) ;
181
+ var element = ReactComponentTreeDevtool . getElement ( id ) ;
182
+ if ( ! element ) {
183
+ // TODO: This check shouldn't be necessary, but in the case that a mount
184
+ // gets aborted due to an exception, processingStack has leftover
185
+ // frames. In contrast, if we clear frames in purgeUnmountedComponents
186
+ // then we get confused if someone starts a new root during a render.
187
+ // Both of these are silly (and cause visible warnings or errors) but
188
+ // are regrettably barely supported.
189
+ return '' ;
190
+ }
191
+ var ownerID = ReactComponentTreeDevtool . getOwnerID ( id ) ;
192
+ var ownerName ;
193
+ if ( ownerID ) {
194
+ ownerName = ReactComponentTreeDevtool . getDisplayName ( ownerID ) ;
195
+ }
196
+ return describeComponentFrame ( name , element . _source , ownerName ) ;
197
+ }
198
+
199
+ var info = '' ;
200
+ if ( topElement ) {
201
+ var type = topElement . type ;
202
+ var name = typeof type === 'function' ?
203
+ type . displayName || type . name :
204
+ type ;
205
+ var owner = topElement . _owner ;
206
+ info += describeComponentFrame (
207
+ name || 'Unknown' ,
208
+ topElement . _source ,
209
+ owner && owner . getName ( )
210
+ ) ;
211
+ }
212
+
213
+ var ii = processingStack . length ;
214
+ if ( ii ) {
215
+ var id ;
216
+ while ( ii -- > 0 ) {
217
+ id = processingStack [ ii ] ;
218
+ info += describeID ( id ) ;
219
+ }
220
+ while ( ( id = ReactComponentTreeDevtool . getParentID ( id ) ) ) {
221
+ info += describeID ( id ) ;
222
+ }
223
+ }
224
+
225
+ return info ;
226
+ } ,
227
+
141
228
getChildIDs ( id ) {
142
229
var item = tree [ id ] ;
143
230
return item ? item . childIDs : [ ] ;
@@ -148,6 +235,11 @@ var ReactComponentTreeDevtool = {
148
235
return item ? item . displayName : 'Unknown' ;
149
236
} ,
150
237
238
+ getElement ( id ) {
239
+ var item = tree [ id ] ;
240
+ return item ? item . element : null ;
241
+ } ,
242
+
151
243
getOwnerID ( id ) {
152
244
var item = tree [ id ] ;
153
245
return item ? item . ownerID : null ;
0 commit comments