@@ -16,9 +16,46 @@ var ReactCurrentOwner = require('ReactCurrentOwner');
16
16
var invariant = require ( 'invariant' ) ;
17
17
var warning = require ( 'warning' ) ;
18
18
19
- var itemByKey = { } ;
20
- var unmountedIDs = { } ;
21
- var rootIDs = { } ;
19
+ function isNative ( fn ) {
20
+ // Based on isNative() from Lodash
21
+ var funcToString = Function . prototype . toString ;
22
+ var hasOwnProperty = Object . prototype . hasOwnProperty ;
23
+ var reIsNative = RegExp ( '^' + funcToString
24
+ // Take an example native function source for comparison
25
+ . call ( hasOwnProperty )
26
+ // Strip regex characters so we can use it for regex
27
+ . replace ( / [ \\ ^ $ . * + ? ( ) [ \] { } | ] / g, '\\$&' )
28
+ // Remove hasOwnProperty from the template to make it generic
29
+ . replace (
30
+ / h a s O w n P r o p e r t y | ( f u n c t i o n ) .* ?(? = \\ \( ) | f o r .+ ?(? = \\ \] ) / g,
31
+ '$1.*?'
32
+ ) + '$'
33
+ ) ;
34
+ try {
35
+ var source = funcToString . call ( fn ) ;
36
+ return reIsNative . test ( source ) ;
37
+ } catch ( err ) {
38
+ return false ;
39
+ }
40
+ }
41
+
42
+ var itemMap ;
43
+ var itemByKey ;
44
+
45
+ var canUseMap = (
46
+ typeof Array . from === 'function' &&
47
+ typeof Map === 'function' &&
48
+ isNative ( Map )
49
+ ) ;
50
+
51
+ if ( canUseMap ) {
52
+ itemMap = new Map ( ) ;
53
+ } else {
54
+ itemByKey = { } ;
55
+ }
56
+
57
+ var unmountedIDs = [ ] ;
58
+ var rootIDs = [ ] ;
22
59
23
60
// Use non-numeric keys to prevent V8 performance issues:
24
61
// https://github.com/facebook/react/pull/7232
@@ -30,25 +67,37 @@ function getIDFromKey(key) {
30
67
}
31
68
32
69
function get ( id ) {
70
+ if ( canUseMap ) {
71
+ return itemMap . get ( id ) ;
72
+ }
33
73
var key = getKeyFromID ( id ) ;
34
74
return itemByKey [ key ] ;
35
75
}
36
76
37
77
function remove ( id ) {
78
+ if ( canUseMap ) {
79
+ itemMap . delete ( id ) ;
80
+ return ;
81
+ }
38
82
var key = getKeyFromID ( id ) ;
39
83
delete itemByKey [ key ] ;
40
84
}
41
85
42
86
function create ( id , element , parentID ) {
43
- var key = getKeyFromID ( id ) ;
44
- itemByKey [ key ] = {
87
+ var item = {
45
88
element,
46
89
parentID,
47
90
text : null ,
48
91
childIDs : [ ] ,
49
92
isMounted : false ,
50
93
updateCount : 0 ,
51
94
} ;
95
+ if ( canUseMap ) {
96
+ itemMap . set ( id , item ) ;
97
+ return ;
98
+ }
99
+ var key = getKeyFromID ( id ) ;
100
+ itemByKey [ key ] = item ;
52
101
}
53
102
54
103
function purgeDeep ( id ) {
@@ -144,10 +193,6 @@ var ReactComponentTreeHook = {
144
193
145
194
onBeforeMountComponent ( id , element , parentID ) {
146
195
create ( id , element , parentID ) ;
147
-
148
- if ( parentID === 0 ) {
149
- rootIDs [ id ] = true ;
150
- }
151
196
} ,
152
197
153
198
onBeforeUpdateComponent ( id , element ) {
@@ -163,6 +208,9 @@ var ReactComponentTreeHook = {
163
208
onMountComponent ( id ) {
164
209
var item = get ( id ) ;
165
210
item . isMounted = true ;
211
+ if ( item . parentID === 0 ) {
212
+ rootIDs . push ( id ) ;
213
+ }
166
214
} ,
167
215
168
216
onUpdateComponent ( id ) {
@@ -184,9 +232,14 @@ var ReactComponentTreeHook = {
184
232
// got a chance to mount, but it still gets an unmounting event during
185
233
// the error boundary cleanup.
186
234
item . isMounted = false ;
235
+ if ( item . parentID === 0 ) {
236
+ var indexInRootIDs = rootIDs . indexOf ( id ) ;
237
+ if ( indexInRootIDs !== - 1 ) {
238
+ rootIDs . splice ( indexInRootIDs , 1 ) ;
239
+ }
240
+ }
187
241
}
188
- unmountedIDs [ id ] = true ;
189
- delete rootIDs [ id ] ;
242
+ unmountedIDs . push ( id ) ;
190
243
} ,
191
244
192
245
purgeUnmountedComponents ( ) {
@@ -195,10 +248,11 @@ var ReactComponentTreeHook = {
195
248
return ;
196
249
}
197
250
198
- for ( var id in unmountedIDs ) {
251
+ for ( var i = 0 ; i < unmountedIDs . length ; i ++ ) {
252
+ var id = unmountedIDs [ i ] ;
199
253
purgeDeep ( id ) ;
200
254
}
201
- unmountedIDs = { } ;
255
+ unmountedIDs . length = 0 ;
202
256
} ,
203
257
204
258
isMounted ( id ) {
@@ -292,10 +346,13 @@ var ReactComponentTreeHook = {
292
346
} ,
293
347
294
348
getRootIDs ( ) {
295
- return Object . keys ( rootIDs ) ;
349
+ return rootIDs ;
296
350
} ,
297
351
298
352
getRegisteredIDs ( ) {
353
+ if ( canUseMap ) {
354
+ return Array . from ( itemMap . keys ( ) ) ;
355
+ }
299
356
return Object . keys ( itemByKey ) . map ( getIDFromKey ) ;
300
357
} ,
301
358
} ;
0 commit comments