refactor of ReactComponentTreeHook to isolate dev methods
Dominic Gannaway committed
Mar 2, 2017 at 16:15 UTC
0e23042e4bba436dceb8ec8ae42856429d2ea69e
5 files changed
+389
-382
src/isomorphic/classic/element/ReactDebugCurrentFrame.js
+4
-9
@@ -18,12 +18,7 @@ import type { DebugID } from 'ReactInstanceType';
18
const ReactDebugCurrentFrame = {};
19
20
if (__DEV__) {
21
- var {
22
- getStackAddendumByID,
23
- getStackAddendumByWorkInProgressFiber,
24
- getCurrentStackAddendum,
25
- } = require('ReactComponentTreeHook');
26
-
21
+ var ReactComponentTreeHook = require('ReactComponentTreeHook');
22
// Component that is being worked on
23
ReactDebugCurrentFrame.current = (null : Fiber | DebugID | null);
24
@@ -38,16 +33,16 @@ if (__DEV__) {
33
if (typeof current === 'number') {
34
// DebugID from Stack.
35
const debugID = current;
41
- stack = getStackAddendumByID(debugID);
36
+ stack = (ReactComponentTreeHook: any).getStackAddendumByID(debugID);
37
} else if (typeof current.tag === 'number') {
38
// This is a Fiber.
39
// The stack will only be correct if this is a work in progress
40
// version and we're calling it during reconciliation.
41
const workInProgress = current;
47
- stack = getStackAddendumByWorkInProgressFiber(workInProgress);
42
+ stack = ReactComponentTreeHook.getStackAddendumByWorkInProgressFiber(workInProgress);
43
}
44
} else if (element !== null) {
50
- stack = getCurrentStackAddendum(element);
45
+ stack = (ReactComponentTreeHook: any).getCurrentStackAddendum(element);
46
}
47
return stack;
48
};
src/isomorphic/hooks/ReactComponentTreeHook.js
+372
-360
@@ -12,7 +12,11 @@
12
13
'use strict';
14
15
-var ReactCurrentOwner = require('ReactCurrentOwner');
15
+import type { ReactElement, Source } from 'ReactElementType';
16
+import type { DebugID } from 'ReactInstanceType';
17
+import type { Fiber } from 'ReactFiber';
18
+
19
+var getComponentName = require('getComponentName');
20
var ReactTypeOfWork = require('ReactTypeOfWork');
21
var {
22
IndeterminateComponent,
@@ -21,144 +25,6 @@ var {
25
HostComponent,
26
} = ReactTypeOfWork;
27
24
-var getComponentName = require('getComponentName');
25
-var invariant = require('fbjs/lib/invariant');
26
-var warning = require('fbjs/lib/warning');
27
-
28
-import type { ReactElement, Source } from 'ReactElementType';
29
-import type { DebugID } from 'ReactInstanceType';
30
-import type { Fiber } from 'ReactFiber';
31
-
32
-function isNative(fn) {
33
- // Based on isNative() from Lodash
34
- var funcToString = Function.prototype.toString;
35
- var hasOwnProperty = Object.prototype.hasOwnProperty;
36
- var reIsNative = RegExp('^' + funcToString
37
- // Take an example native function source for comparison
38
- .call(hasOwnProperty)
39
- // Strip regex characters so we can use it for regex
40
- .replace(/[\\^$.*+?()[\]{}|]/g, '\\$&')
41
- // Remove hasOwnProperty from the template to make it generic
42
- .replace(
43
- /hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,
44
- '$1.*?'
45
- ) + '$'
46
- );
47
- try {
48
- var source = funcToString.call(fn);
49
- return reIsNative.test(source);
50
- } catch (err) {
51
- return false;
52
- }
53
-}
54
-
55
-var canUseCollections = (
56
- // Array.from
57
- typeof Array.from === 'function' &&
58
- // Map
59
- typeof Map === 'function' &&
60
- isNative(Map) &&
61
- // Map.prototype.keys
62
- Map.prototype != null &&
63
- typeof Map.prototype.keys === 'function' &&
64
- isNative(Map.prototype.keys) &&
65
- // Set
66
- typeof Set === 'function' &&
67
- isNative(Set) &&
68
- // Set.prototype.keys
69
- Set.prototype != null &&
70
- typeof Set.prototype.keys === 'function' &&
71
- isNative(Set.prototype.keys)
72
-);
73
-
74
-var setItem;
75
-var getItem;
76
-var removeItem;
77
-var getItemIDs;
78
-var addRoot;
79
-var removeRoot;
80
-var getRootIDs;
81
-
82
-if (canUseCollections) {
83
- var itemMap = new Map();
84
- var rootIDSet = new Set();
85
-
86
- setItem = function(id, item) {
87
- itemMap.set(id, item);
88
- };
89
- getItem = function(id) {
90
- return itemMap.get(id);
91
- };
92
- removeItem = function(id) {
93
- itemMap.delete(id);
94
- };
95
- getItemIDs = function() {
96
- return Array.from(itemMap.keys());
97
- };
98
-
99
- addRoot = function(id) {
100
- rootIDSet.add(id);
101
- };
102
- removeRoot = function(id) {
103
- rootIDSet.delete(id);
104
- };
105
- getRootIDs = function() {
106
- return Array.from(rootIDSet.keys());
107
- };
108
-
109
-} else {
110
- var itemByKey = {};
111
- var rootByKey = {};
112
-
113
- // Use non-numeric keys to prevent V8 performance issues:
114
- // https://github.com/facebook/react/pull/7232
115
- var getKeyFromID = function(id: DebugID): string {
116
- return '.' + id;
117
- };
118
- var getIDFromKey = function(key: string): DebugID {
119
- return parseInt(key.substr(1), 10);
120
- };
121
-
122
- setItem = function(id, item) {
123
- var key = getKeyFromID(id);
124
- itemByKey[key] = item;
125
- };
126
- getItem = function(id) {
127
- var key = getKeyFromID(id);
128
- return itemByKey[key];
129
- };
130
- removeItem = function(id) {
131
- var key = getKeyFromID(id);
132
- delete itemByKey[key];
133
- };
134
- getItemIDs = function() {
135
- return Object.keys(itemByKey).map(getIDFromKey);
136
- };
137
-
138
- addRoot = function(id) {
139
- var key = getKeyFromID(id);
140
- rootByKey[key] = true;
141
- };
142
- removeRoot = function(id) {
143
- var key = getKeyFromID(id);
144
- delete rootByKey[key];
145
- };
146
- getRootIDs = function() {
147
- return Object.keys(rootByKey).map(getIDFromKey);
148
- };
149
-}
150
-
151
-var unmountedIDs: Array<DebugID> = [];
152
-
153
-function purgeDeep(id) {
154
- var item = getItem(id);
155
- if (item) {
156
- var {childIDs} = item;
157
- removeItem(id);
158
- childIDs.forEach(purgeDeep);
159
- }
160
-}
161
-
28
function describeComponentFrame(name, source, ownerName) {
29
return '\n in ' + (name || 'Unknown') + (
30
source ?
@@ -170,35 +36,6 @@ function describeComponentFrame(name, source, ownerName) {
36
);
37
}
38
173
-function getDisplayName(element: ?ReactElement): string {
174
- if (element == null) {
175
- return '#empty';
176
- } else if (typeof element === 'string' || typeof element === 'number') {
177
- return '#text';
178
- } else if (typeof element.type === 'string') {
179
- return element.type;
180
- } else {
181
- return element.type.displayName || element.type.name || 'Unknown';
182
- }
183
-}
184
-
185
-function describeID(id: DebugID): string {
186
- var name = ReactComponentTreeHook.getDisplayName(id);
187
- var element = ReactComponentTreeHook.getElement(id);
188
- var ownerID = ReactComponentTreeHook.getOwnerID(id);
189
- var ownerName;
190
- if (ownerID) {
191
- ownerName = ReactComponentTreeHook.getDisplayName(ownerID);
192
- }
193
- warning(
194
- element,
195
- 'ReactComponentTreeHook: Missing React element for debugID %s when ' +
196
- 'building stack',
197
- id
198
- );
199
- return describeComponentFrame(name, element && element._source, ownerName);
200
-}
201
-
39
function describeFiber(fiber : Fiber) : string {
40
switch (fiber.tag) {
41
case IndeterminateComponent:
@@ -219,230 +56,405 @@ function describeFiber(fiber : Fiber) : string {
56
}
57
58
var ReactComponentTreeHook = {
222
- onSetChildren(id: DebugID, nextChildIDs: Array<DebugID>): void {
223
- var item = getItem(id);
224
- invariant(item, 'Item must have been set');
225
- item.childIDs = nextChildIDs;
226
-
227
- for (var i = 0; i < nextChildIDs.length; i++) {
228
- var nextChildID = nextChildIDs[i];
229
- var nextChild = getItem(nextChildID);
230
- invariant(
231
- nextChild,
232
- 'Expected hook events to fire for the child ' +
233
- 'before its parent includes it in onSetChildren().'
234
- );
235
- invariant(
236
- nextChild.childIDs != null ||
237
- typeof nextChild.element !== 'object' ||
238
- nextChild.element == null,
239
- 'Expected onSetChildren() to fire for a container child ' +
240
- 'before its parent includes it in onSetChildren().'
241
- );
242
- invariant(
243
- nextChild.isMounted,
244
- 'Expected onMountComponent() to fire for the child ' +
245
- 'before its parent includes it in onSetChildren().'
246
- );
247
- if (nextChild.parentID == null) {
248
- nextChild.parentID = id;
249
- // TODO: This shouldn't be necessary but mounting a new root during in
250
- // componentWillMount currently causes not-yet-mounted components to
251
- // be purged from our tree data so their parent id is missing.
252
- }
253
- invariant(
254
- nextChild.parentID === id,
255
- 'Expected onBeforeMountComponent() parent and onSetChildren() to ' +
256
- 'be consistent (%s has parents %s and %s).',
257
- nextChildID,
258
- nextChild.parentID,
259
- id
260
- );
261
- }
59
+ // This function can only be called with a work-in-progress fiber and
60
+ // only during begin or complete phase. Do not call it under any other
61
+ // circumstances.
62
+ getStackAddendumByWorkInProgressFiber(workInProgress : Fiber) : string {
63
+ var info = '';
64
+ var node = workInProgress;
65
+ do {
66
+ info += describeFiber(node);
67
+ // Otherwise this return pointer might point to the wrong tree:
68
+ node = node.return;
69
+ } while (node);
70
+ return info;
71
},
72
+};
73
264
- onBeforeMountComponent(id: DebugID, element: ReactElement, parentID: DebugID): void {
265
- var item = {
266
- element,
267
- parentID,
268
- text: null,
269
- childIDs: [],
270
- isMounted: false,
271
- updateCount: 0,
74
+if (__DEV__) {
75
+ var ReactCurrentOwner = require('ReactCurrentOwner');
76
+ var invariant = require('fbjs/lib/invariant');
77
+ var warning = require('fbjs/lib/warning');
78
+
79
+ var isNative = function(fn) {
80
+ // Based on isNative() from Lodash
81
+ var funcToString = Function.prototype.toString;
82
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
83
+ var reIsNative = RegExp('^' + funcToString
84
+ // Take an example native function source for comparison
85
+ .call(hasOwnProperty)
86
+ // Strip regex characters so we can use it for regex
87
+ .replace(/[\\^$.*+?()[\]{}|]/g, '\\$&')
88
+ // Remove hasOwnProperty from the template to make it generic
89
+ .replace(
90
+ /hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,
91
+ '$1.*?'
92
+ ) + '$'
93
+ );
94
+ try {
95
+ var source = funcToString.call(fn);
96
+ return reIsNative.test(source);
97
+ } catch (err) {
98
+ return false;
99
+ }
100
+ };
101
+
102
+ var canUseCollections = (
103
+ // Array.from
104
+ typeof Array.from === 'function' &&
105
+ // Map
106
+ typeof Map === 'function' &&
107
+ isNative(Map) &&
108
+ // Map.prototype.keys
109
+ Map.prototype != null &&
110
+ typeof Map.prototype.keys === 'function' &&
111
+ isNative(Map.prototype.keys) &&
112
+ // Set
113
+ typeof Set === 'function' &&
114
+ isNative(Set) &&
115
+ // Set.prototype.keys
116
+ Set.prototype != null &&
117
+ typeof Set.prototype.keys === 'function' &&
118
+ isNative(Set.prototype.keys)
119
+ );
120
+
121
+ var setItem;
122
+ var getItem;
123
+ var removeItem;
124
+ var getItemIDs;
125
+ var addRoot;
126
+ var removeRoot;
127
+ var getRootIDs;
128
+
129
+ if (canUseCollections) {
130
+ var itemMap = new Map();
131
+ var rootIDSet = new Set();
132
+
133
+ setItem = function(id, item) {
134
+ itemMap.set(id, item);
135
+ };
136
+ getItem = function(id) {
137
+ return itemMap.get(id);
138
+ };
139
+ removeItem = function(id) {
140
+ itemMap.delete(id);
141
+ };
142
+ getItemIDs = function() {
143
+ return Array.from(itemMap.keys());
144
};
273
- setItem(id, item);
274
- },
145
276
- onBeforeUpdateComponent(id: DebugID, element: ReactElement): void {
277
- var item = getItem(id);
278
- if (!item || !item.isMounted) {
279
- // We may end up here as a result of setState() in componentWillUnmount().
280
- // In this case, ignore the element.
281
- return;
282
- }
283
- item.element = element;
284
- },
146
+ addRoot = function(id) {
147
+ rootIDSet.add(id);
148
+ };
149
+ removeRoot = function(id) {
150
+ rootIDSet.delete(id);
151
+ };
152
+ getRootIDs = function() {
153
+ return Array.from(rootIDSet.keys());
154
+ };
155
286
- onMountComponent(id: DebugID): void {
287
- var item = getItem(id);
288
- invariant(item, 'Item must have been set');
289
- item.isMounted = true;
290
- var isRoot = item.parentID === 0;
291
- if (isRoot) {
292
- addRoot(id);
293
- }
294
- },
156
+ } else {
157
+ var itemByKey = {};
158
+ var rootByKey = {};
159
296
- onUpdateComponent(id: DebugID): void {
297
- var item = getItem(id);
298
- if (!item || !item.isMounted) {
299
- // We may end up here as a result of setState() in componentWillUnmount().
300
- // In this case, ignore the element.
301
- return;
302
- }
303
- item.updateCount++;
304
- },
160
+ // Use non-numeric keys to prevent V8 performance issues:
161
+ // https://github.com/facebook/react/pull/7232
162
+ var getKeyFromID = function(id: DebugID): string {
163
+ return '.' + id;
164
+ };
165
+ var getIDFromKey = function(key: string): DebugID {
166
+ return parseInt(key.substr(1), 10);
167
+ };
168
306
- onUnmountComponent(id: DebugID): void {
169
+ setItem = function(id, item) {
170
+ var key = getKeyFromID(id);
171
+ itemByKey[key] = item;
172
+ };
173
+ getItem = function(id) {
174
+ var key = getKeyFromID(id);
175
+ return itemByKey[key];
176
+ };
177
+ removeItem = function(id) {
178
+ var key = getKeyFromID(id);
179
+ delete itemByKey[key];
180
+ };
181
+ getItemIDs = function() {
182
+ return Object.keys(itemByKey).map(getIDFromKey);
183
+ };
184
+
185
+ addRoot = function(id) {
186
+ var key = getKeyFromID(id);
187
+ rootByKey[key] = true;
188
+ };
189
+ removeRoot = function(id) {
190
+ var key = getKeyFromID(id);
191
+ delete rootByKey[key];
192
+ };
193
+ getRootIDs = function() {
194
+ return Object.keys(rootByKey).map(getIDFromKey);
195
+ };
196
+ }
197
+
198
+ var unmountedIDs: Array<DebugID> = [];
199
+
200
+ var purgeDeep = function(id) {
201
var item = getItem(id);
202
if (item) {
309
- // We need to check if it exists.
310
- // `item` might not exist if it is inside an error boundary, and a sibling
311
- // error boundary child threw while mounting. Then this instance never
312
- // got a chance to mount, but it still gets an unmounting event during
313
- // the error boundary cleanup.
314
- item.isMounted = false;
315
- var isRoot = item.parentID === 0;
316
- if (isRoot) {
317
- removeRoot(id);
318
- }
203
+ var {childIDs} = item;
204
+ removeItem(id);
205
+ childIDs.forEach(purgeDeep);
206
}
320
- unmountedIDs.push(id);
321
- },
207
+ };
208
323
- purgeUnmountedComponents(): void {
324
- if (ReactComponentTreeHook._preventPurging) {
325
- // Should only be used for testing.
326
- return;
209
+ var getDisplayName = function(element: ?ReactElement): string {
210
+ if (element == null) {
211
+ return '#empty';
212
+ } else if (typeof element === 'string' || typeof element === 'number') {
213
+ return '#text';
214
+ } else if (typeof element.type === 'string') {
215
+ return element.type;
216
+ } else {
217
+ return element.type.displayName || element.type.name || 'Unknown';
218
}
219
+ };
220
329
- for (var i = 0; i < unmountedIDs.length; i++) {
330
- var id = unmountedIDs[i];
331
- purgeDeep(id);
221
+ var describeID = function(id: DebugID): string {
222
+ var name = getDisplayName((id: any));
223
+ var element = getElement(id);
224
+ var ownerID: any = getOwnerID(id);
225
+ var ownerName;
226
+ if (ownerID) {
227
+ ownerName = getDisplayName(ownerID);
228
}
333
- unmountedIDs.length = 0;
334
- },
335
-
336
- isMounted(id: DebugID): boolean {
337
- var item = getItem(id);
338
- return item ? item.isMounted : false;
339
- },
229
+ warning(
230
+ element,
231
+ 'ReactComponentTreeHook: Missing React element for debugID %s when ' +
232
+ 'building stack',
233
+ id
234
+ );
235
+ return describeComponentFrame(name, element && element._source, ownerName);
236
+ };
237
341
- getCurrentStackAddendum(topElement: ?ReactElement): string {
342
- var info = '';
343
- if (topElement) {
344
- var name = getDisplayName(topElement);
345
- var owner = topElement._owner;
346
- info += describeComponentFrame(
347
- name,
348
- topElement._source,
349
- owner && getComponentName(owner)
350
- );
238
+ var getOwnerID = function(id: DebugID): ?DebugID {
239
+ var element = getElement(id);
240
+ if (!element || !element._owner) {
241
+ return null;
242
}
243
+ return element._owner._debugID;
244
+ };
245
353
- var currentOwner = ReactCurrentOwner.current;
354
- if (currentOwner) {
355
- if (typeof currentOwner.tag === 'number') {
356
- const workInProgress = ((currentOwner : any) : Fiber);
357
- // Safe because if current owner exists, we are reconciling,
358
- // and it is guaranteed to be the work-in-progress version.
359
- info += ReactComponentTreeHook.getStackAddendumByWorkInProgressFiber(workInProgress);
360
- } else if (typeof currentOwner._debugID === 'number') {
361
- info += ReactComponentTreeHook.getStackAddendumByID(currentOwner._debugID);
362
- }
363
- }
364
- return info;
365
- },
246
+ var getElement = function(id: DebugID): ?ReactElement {
247
+ var item = getItem(id);
248
+ return item ? item.element : null;
249
+ };
250
367
- getStackAddendumByID(id: ?DebugID): string {
251
+ var getParentID = function(id: DebugID): ?DebugID {
252
+ var item = getItem(id);
253
+ return item ? item.parentID : null;
254
+ };
255
+
256
+ var getStackAddendumByID = function(id: ?DebugID): string {
257
var info = '';
258
while (id) {
259
info += describeID(id);
371
- id = ReactComponentTreeHook.getParentID(id);
260
+ id = getParentID(id);
261
}
262
return info;
374
- },
263
+ };
264
376
- // This function can only be called with a work-in-progress fiber and
377
- // only during begin or complete phase. Do not call it under any other
378
- // circumstances.
379
- getStackAddendumByWorkInProgressFiber(workInProgress : Fiber) : string {
380
- var info = '';
381
- var node = workInProgress;
382
- do {
383
- info += describeFiber(node);
384
- // Otherwise this return pointer might point to the wrong tree:
385
- node = node.return;
386
- } while (node);
387
- return info;
388
- },
265
+ ReactComponentTreeHook = Object.assign({}, ReactComponentTreeHook, {
266
+ onSetChildren(id: DebugID, nextChildIDs: Array<DebugID>): void {
267
+ var item = getItem(id);
268
+ invariant(item, 'Item must have been set');
269
+ item.childIDs = nextChildIDs;
270
+
271
+ for (var i = 0; i < nextChildIDs.length; i++) {
272
+ var nextChildID = nextChildIDs[i];
273
+ var nextChild = getItem(nextChildID);
274
+ invariant(
275
+ nextChild,
276
+ 'Expected hook events to fire for the child ' +
277
+ 'before its parent includes it in onSetChildren().'
278
+ );
279
+ invariant(
280
+ nextChild.childIDs != null ||
281
+ typeof nextChild.element !== 'object' ||
282
+ nextChild.element == null,
283
+ 'Expected onSetChildren() to fire for a container child ' +
284
+ 'before its parent includes it in onSetChildren().'
285
+ );
286
+ invariant(
287
+ nextChild.isMounted,
288
+ 'Expected onMountComponent() to fire for the child ' +
289
+ 'before its parent includes it in onSetChildren().'
290
+ );
291
+ if (nextChild.parentID == null) {
292
+ nextChild.parentID = id;
293
+ // TODO: This shouldn't be necessary but mounting a new root during in
294
+ // componentWillMount currently causes not-yet-mounted components to
295
+ // be purged from our tree data so their parent id is missing.
296
+ }
297
+ invariant(
298
+ nextChild.parentID === id,
299
+ 'Expected onBeforeMountComponent() parent and onSetChildren() to ' +
300
+ 'be consistent (%s has parents %s and %s).',
301
+ nextChildID,
302
+ nextChild.parentID,
303
+ id
304
+ );
305
+ }
306
+ },
307
+
308
+ onBeforeMountComponent(id: DebugID, element: ReactElement, parentID: DebugID): void {
309
+ var item = {
310
+ element,
311
+ parentID,
312
+ text: null,
313
+ childIDs: [],
314
+ isMounted: false,
315
+ updateCount: 0,
316
+ };
317
+ setItem(id, item);
318
+ },
319
+
320
+ onBeforeUpdateComponent(id: DebugID, element: ReactElement): void {
321
+ var item = getItem(id);
322
+ if (!item || !item.isMounted) {
323
+ // We may end up here as a result of setState() in componentWillUnmount().
324
+ // In this case, ignore the element.
325
+ return;
326
+ }
327
+ item.element = element;
328
+ },
329
390
- getChildIDs(id: DebugID): Array<DebugID> {
391
- var item = getItem(id);
392
- return item ? item.childIDs : [];
393
- },
330
+ onMountComponent(id: DebugID): void {
331
+ var item = getItem(id);
332
+ invariant(item, 'Item must have been set');
333
+ item.isMounted = true;
334
+ var isRoot = item.parentID === 0;
335
+ if (isRoot) {
336
+ addRoot(id);
337
+ }
338
+ },
339
+
340
+ onUpdateComponent(id: DebugID): void {
341
+ var item = getItem(id);
342
+ if (!item || !item.isMounted) {
343
+ // We may end up here as a result of setState() in componentWillUnmount().
344
+ // In this case, ignore the element.
345
+ return;
346
+ }
347
+ item.updateCount++;
348
+ },
349
+
350
+ onUnmountComponent(id: DebugID): void {
351
+ var item = getItem(id);
352
+ if (item) {
353
+ // We need to check if it exists.
354
+ // `item` might not exist if it is inside an error boundary, and a sibling
355
+ // error boundary child threw while mounting. Then this instance never
356
+ // got a chance to mount, but it still gets an unmounting event during
357
+ // the error boundary cleanup.
358
+ item.isMounted = false;
359
+ var isRoot = item.parentID === 0;
360
+ if (isRoot) {
361
+ removeRoot(id);
362
+ }
363
+ }
364
+ unmountedIDs.push(id);
365
+ },
366
395
- getDisplayName(id: DebugID): ?string {
396
- var element = ReactComponentTreeHook.getElement(id);
397
- if (!element) {
398
- return null;
399
- }
400
- return getDisplayName(element);
401
- },
367
+ purgeUnmountedComponents(): void {
368
+ if (ReactComponentTreeHook._preventPurging) {
369
+ // Should only be used for testing.
370
+ return;
371
+ }
372
403
- getElement(id: DebugID): ?ReactElement {
404
- var item = getItem(id);
405
- return item ? item.element : null;
406
- },
373
+ for (var i = 0; i < unmountedIDs.length; i++) {
374
+ var id = unmountedIDs[i];
375
+ purgeDeep(id);
376
+ }
377
+ unmountedIDs.length = 0;
378
+ },
379
+
380
+ isMounted(id: DebugID): boolean {
381
+ var item = getItem(id);
382
+ return item ? item.isMounted : false;
383
+ },
384
+
385
+ getCurrentStackAddendum(topElement: ?ReactElement): string {
386
+ var info = '';
387
+ if (topElement) {
388
+ var name = getDisplayName(topElement);
389
+ var owner = topElement._owner;
390
+ info += describeComponentFrame(
391
+ name,
392
+ topElement._source,
393
+ owner && getComponentName(owner)
394
+ );
395
+ }
396
408
- getOwnerID(id: DebugID): ?DebugID {
409
- var element = ReactComponentTreeHook.getElement(id);
410
- if (!element || !element._owner) {
411
- return null;
412
- }
413
- return element._owner._debugID;
414
- },
397
+ var currentOwner = ReactCurrentOwner.current;
398
+ if (currentOwner) {
399
+ if (typeof currentOwner.tag === 'number') {
400
+ const workInProgress = ((currentOwner : any) : Fiber);
401
+ // Safe because if current owner exists, we are reconciling,
402
+ // and it is guaranteed to be the work-in-progress version.
403
+ info += ReactComponentTreeHook.getStackAddendumByWorkInProgressFiber(workInProgress);
404
+ } else if (typeof currentOwner._debugID === 'number') {
405
+ info += getStackAddendumByID(currentOwner._debugID);
406
+ }
407
+ }
408
+ return info;
409
+ },
410
416
- getParentID(id: DebugID): ?DebugID {
417
- var item = getItem(id);
418
- return item ? item.parentID : null;
419
- },
411
+ getStackAddendumByID,
412
421
- getSource(id: DebugID): ?Source {
422
- var item = getItem(id);
423
- var element = item ? item.element : null;
424
- var source = element != null ? element._source : null;
425
- return source;
426
- },
413
+ getChildIDs(id: DebugID): Array<DebugID> {
414
+ var item = getItem(id);
415
+ return item ? item.childIDs : [];
416
+ },
417
428
- getText(id: DebugID): ?string {
429
- var element = ReactComponentTreeHook.getElement(id);
430
- if (typeof element === 'string') {
431
- return element;
432
- } else if (typeof element === 'number') {
433
- return '' + element;
434
- } else {
435
- return null;
436
- }
437
- },
418
+ getDisplayName(id: DebugID): ?string {
419
+ var element = getElement(id);
420
+ if (!element) {
421
+ return null;
422
+ }
423
+ return getDisplayName(element);
424
+ },
425
+
426
+ getElement,
427
+
428
+ getOwnerID,
429
+
430
+ getParentID,
431
+
432
+ getSource(id: DebugID): ?Source {
433
+ var item = getItem(id);
434
+ var element = item ? item.element : null;
435
+ var source = element != null ? element._source : null;
436
+ return source;
437
+ },
438
+
439
+ getText(id: DebugID): ?string {
440
+ var element = getElement(id);
441
+ if (typeof element === 'string') {
442
+ return element;
443
+ } else if (typeof element === 'number') {
444
+ return '' + element;
445
+ } else {
446
+ return null;
447
+ }
448
+ },
449
439
- getUpdateCount(id: DebugID): number {
440
- var item = getItem(id);
441
- return item ? item.updateCount : 0;
442
- },
450
+ getUpdateCount(id: DebugID): number {
451
+ var item = getItem(id);
452
+ return item ? item.updateCount : 0;
453
+ },
454
444
- getRootIDs,
445
- getRegisteredIDs: getItemIDs,
446
-};
455
+ getRootIDs,
456
+ getRegisteredIDs: getItemIDs,
457
+ });
458
+}
459
460
module.exports = ReactComponentTreeHook;
src/renderers/shared/ReactDebugTool.js
+11
-11
@@ -108,22 +108,22 @@ if (__DEV__) {
108
var lifeCycleTimerHasWarned = false;
109
110
const clearHistory = function() {
111
- ReactComponentTreeHook.purgeUnmountedComponents();
111
+ (ReactComponentTreeHook: any).purgeUnmountedComponents();
112
ReactHostOperationHistoryHook.clearHistory();
113
};
114
115
const getTreeSnapshot = function(registeredIDs) {
116
return registeredIDs.reduce((tree, id) => {
117
- var ownerID = ReactComponentTreeHook.getOwnerID(id);
118
- var parentID = ReactComponentTreeHook.getParentID(id);
117
+ var ownerID = (ReactComponentTreeHook: any).getOwnerID(id);
118
+ var parentID = (ReactComponentTreeHook: any).getParentID(id);
119
tree[id] = {
120
- displayName: ReactComponentTreeHook.getDisplayName(id),
121
- text: ReactComponentTreeHook.getText(id),
122
- updateCount: ReactComponentTreeHook.getUpdateCount(id),
123
- childIDs: ReactComponentTreeHook.getChildIDs(id),
120
+ displayName: (ReactComponentTreeHook: any).getDisplayName(id),
121
+ text: (ReactComponentTreeHook: any).getText(id),
122
+ updateCount: (ReactComponentTreeHook: any).getUpdateCount(id),
123
+ childIDs: (ReactComponentTreeHook: any).getChildIDs(id),
124
// Text nodes don't have owners but this is close enough.
125
ownerID: ownerID ||
126
- parentID && ReactComponentTreeHook.getOwnerID(parentID) ||
126
+ parentID && (ReactComponentTreeHook: any).getOwnerID(parentID) ||
127
0,
128
parentID,
129
};
@@ -144,7 +144,7 @@ if (__DEV__) {
144
}
145
146
if (previousMeasurements.length || previousOperations.length) {
147
- var registeredIDs = ReactComponentTreeHook.getRegisteredIDs();
147
+ var registeredIDs = (ReactComponentTreeHook: any).getRegisteredIDs();
148
flushHistory.push({
149
duration: performanceNow() - previousStartTime,
150
measurements: previousMeasurements || [],
@@ -253,7 +253,7 @@ if (__DEV__) {
253
if (!isProfiling || !canUsePerformanceMeasure) {
254
return false;
255
}
256
- var element = ReactComponentTreeHook.getElement(debugID);
256
+ var element = (ReactComponentTreeHook: any).getElement(debugID);
257
if (element == null || typeof element !== 'object') {
258
return false;
259
}
@@ -280,7 +280,7 @@ if (__DEV__) {
280
}
281
282
var markName = `${debugID}::${markType}`;
283
- var displayName = ReactComponentTreeHook.getDisplayName(debugID) || 'Unknown';
283
+ var displayName = (ReactComponentTreeHook: any).getDisplayName(debugID) || 'Unknown';
284
285
// Chrome has an issue of dropping markers recorded too fast:
286
// https://bugs.chromium.org/p/chromium/issues/detail?id=640652
src/renderers/shared/stack/reconciler/ReactRef.js
+1
-1
@@ -53,7 +53,7 @@ function attachRef(ref, component, owner) {
53
'Stateless function components cannot be given refs. ' +
54
'Attempts to access this ref will fail.%s%s',
55
info,
56
- ReactComponentTreeHook.getStackAddendumByID(component._debugID)
56
+ (ReactComponentTreeHook: any).getStackAddendumByID(component._debugID)
57
);
58
}
59
}
src/shared/utils/flattenChildren.js
+1
-1
@@ -58,7 +58,7 @@ function flattenSingleChildIntoContext(
58
'`%s`. Child keys must be unique; when two children share a key, only ' +
59
'the first child will be used.%s',
60
KeyEscapeUtils.unescape(name),
61
- ReactComponentTreeHook.getStackAddendumByID(selfDebugID)
61
+ (ReactComponentTreeHook: any).getStackAddendumByID(selfDebugID)
62
);
63
}
64
}