@@ -631,7 +631,8 @@ export function attach(
631
631
// In this case, we should wait until the rest of the passive effects have run,
632
632
// but we shouldn't wait until the next commit because that might be a long time.
633
633
// This would also cause "tearing" between an inspected Component and the tree view.
634
- // Then again we don't want to flush too soon because rendering might stil be going on.
634
+ // Then again we don't want to flush too soon because this could be an error during async rendering.
635
+ // Use a debounce technique to ensure that we'll eventually flush.
635
636
flushPendingErrorsAndWarningsAfterDelay ( ) ;
636
637
}
637
638
@@ -1205,10 +1206,12 @@ export function attach(
1205
1206
}
1206
1207
}
1207
1208
1208
- const pendingOperations : Array < number > = [ ] ;
1209
+ type OperationsArray = Array < number > ;
1210
+
1211
+ const pendingOperations : OperationsArray = [ ] ;
1209
1212
const pendingRealUnmountedIDs : Array < number > = [ ] ;
1210
1213
const pendingSimulatedUnmountedIDs : Array < number > = [ ] ;
1211
- let pendingOperationsQueue : Array < Array < number > > | null = [ ] ;
1214
+ let pendingOperationsQueue : Array < OperationsArray > | null = [ ] ;
1212
1215
const pendingStringTable : Map < string , number > = new Map ( ) ;
1213
1216
let pendingStringTableLength : number = 0 ;
1214
1217
let pendingUnmountedRootID : number | null = null ;
@@ -1225,55 +1228,57 @@ export function attach(
1225
1228
pendingOperations . push ( op ) ;
1226
1229
}
1227
1230
1231
+ function flushOrQueueOperations ( operations : OperationsArray ) : void {
1232
+ if ( pendingOperationsQueue !== null ) {
1233
+ pendingOperationsQueue . push ( operations ) ;
1234
+ } else {
1235
+ hook . emit ( 'operations' , operations ) ;
1236
+ }
1237
+ }
1238
+
1228
1239
let flushPendingErrorsAndWarningsAfterDelayTimeoutID = null ;
1229
- function flushPendingErrorsAndWarningsAfterDelay ( ) {
1240
+
1241
+ function clearPendingErrorsAndWarningsAfterDelay ( ) {
1230
1242
if ( flushPendingErrorsAndWarningsAfterDelayTimeoutID !== null ) {
1231
1243
clearTimeout ( flushPendingErrorsAndWarningsAfterDelayTimeoutID ) ;
1232
1244
}
1245
+ }
1246
+
1247
+ function flushPendingErrorsAndWarningsAfterDelay ( ) {
1248
+ clearPendingErrorsAndWarningsAfterDelay ( ) ;
1233
1249
1234
1250
flushPendingErrorsAndWarningsAfterDelayTimeoutID = setTimeout ( ( ) => {
1235
1251
flushPendingErrorsAndWarningsAfterDelayTimeoutID = null ;
1236
1252
1237
1253
if ( pendingOperations . length > 0 ) {
1238
- // On the off chance that somethign else has pushed pending operations,
1254
+ // On the off chance that something else has pushed pending operations,
1239
1255
// we should bail on warnings; it's probably not safe to push midway.
1240
1256
return ;
1241
1257
}
1242
1258
1243
1259
recordPendingErrorsAndWarnings ( ) ;
1244
1260
1245
1261
if ( pendingOperations . length === 0 ) {
1246
- // No warnings or errors to flush.
1262
+ // No warnings or errors to flush; we can bail out early here too .
1247
1263
return ;
1248
1264
}
1249
1265
1250
- const operations = new Array ( 2 + 1 + pendingOperations . length ) ;
1251
-
1252
- // Identify which renderer this update is coming from .
1253
- // This enables roots to be mapped to renderers,
1254
- // Which in turn enables fiber props, states, and hooks to be inspected.
1255
- let i = 0 ;
1256
- operations [ i ++ ] = rendererID ;
1257
- operations [ i ++ ] = currentRootID ; // Use this ID in case the root was unmounted!
1258
- operations [ i ++ ] = 0 ; // String table size
1266
+ // We can create a smaller operations array than flushPendingEvents()
1267
+ // because we only need to flush warning and error counts.
1268
+ // Only a few pieces of fixed information are required up front .
1269
+ const operations : OperationsArray = new Array (
1270
+ 3 + pendingOperations . length ,
1271
+ ) ;
1272
+ operations [ 0 ] = rendererID ;
1273
+ operations [ 1 ] = currentRootID ; // Use this ID in case the root was unmounted!
1274
+ operations [ 2 ] = 0 ; // String table size
1259
1275
1260
1276
// Fill in the rest of the operations.
1261
1277
for ( let j = 0 ; j < pendingOperations . length ; j ++ ) {
1262
- operations [ i + j ] = pendingOperations [ j ] ;
1278
+ operations [ 3 + j ] = pendingOperations [ j ] ;
1263
1279
}
1264
1280
1265
- // Let the frontend know about tree operations.
1266
- // The first value in this array will identify which root it corresponds to,
1267
- // so we do no longer need to dispatch a separate root-committed event.
1268
- if ( pendingOperationsQueue !== null ) {
1269
- // Until the frontend has been connected, store the tree operations.
1270
- // This will let us avoid walking the tree later when the frontend connects,
1271
- // and it enables the Profiler's reload-and-profile functionality to work as well.
1272
- pendingOperationsQueue . push ( operations ) ;
1273
- } else {
1274
- // If we've already connected to the frontend, just pass the operations through.
1275
- hook . emit ( 'operations' , operations ) ;
1276
- }
1281
+ flushOrQueueOperations ( operations ) ;
1277
1282
1278
1283
pendingOperations . length = 0 ;
1279
1284
} , 1000 ) ;
@@ -1291,10 +1296,7 @@ export function attach(
1291
1296
}
1292
1297
1293
1298
function recordPendingErrorsAndWarnings ( ) {
1294
- if ( flushPendingErrorsAndWarningsAfterDelayTimeoutID !== null ) {
1295
- clearTimeout ( flushPendingErrorsAndWarningsAfterDelayTimeoutID ) ;
1296
- flushPendingErrorsAndWarningsAfterDelayTimeoutID = null ;
1297
- }
1299
+ clearPendingErrorsAndWarningsAfterDelay ( ) ;
1298
1300
1299
1301
fibersWithChangedErrorOrWarningCounts . forEach ( fiberID => {
1300
1302
const fiber = idToFiberMap . get ( fiberID ) ;
@@ -1432,18 +1434,9 @@ export function attach(
1432
1434
i += pendingOperations . length ;
1433
1435
1434
1436
// Let the frontend know about tree operations.
1435
- // The first value in this array will identify which root it corresponds to,
1436
- // so we do no longer need to dispatch a separate root-committed event.
1437
- if ( pendingOperationsQueue !== null ) {
1438
- // Until the frontend has been connected, store the tree operations.
1439
- // This will let us avoid walking the tree later when the frontend connects,
1440
- // and it enables the Profiler's reload-and-profile functionality to work as well.
1441
- pendingOperationsQueue . push ( operations ) ;
1442
- } else {
1443
- // If we've already connected to the frontend, just pass the operations through.
1444
- hook . emit ( 'operations' , operations ) ;
1445
- }
1437
+ flushOrQueueOperations ( operations ) ;
1446
1438
1439
+ // Reset all of the pending state now that we've told the frontend about it.
1447
1440
pendingOperations . length = 0 ;
1448
1441
pendingRealUnmountedIDs . length = 0 ;
1449
1442
pendingSimulatedUnmountedIDs . length = 0 ;
0 commit comments