@@ -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,56 @@ 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 ) ;
1244
+ flushPendingErrorsAndWarningsAfterDelayTimeoutID = null ;
1232
1245
}
1246
+ }
1247
+
1248
+ function flushPendingErrorsAndWarningsAfterDelay ( ) {
1249
+ clearPendingErrorsAndWarningsAfterDelay ( ) ;
1233
1250
1234
1251
flushPendingErrorsAndWarningsAfterDelayTimeoutID = setTimeout ( ( ) => {
1235
1252
flushPendingErrorsAndWarningsAfterDelayTimeoutID = null ;
1236
1253
1237
1254
if ( pendingOperations . length > 0 ) {
1238
- // On the off chance that somethign else has pushed pending operations,
1255
+ // On the off chance that something else has pushed pending operations,
1239
1256
// we should bail on warnings; it's probably not safe to push midway.
1240
1257
return ;
1241
1258
}
1242
1259
1243
1260
recordPendingErrorsAndWarnings ( ) ;
1244
1261
1245
1262
if ( pendingOperations . length === 0 ) {
1246
- // No warnings or errors to flush.
1263
+ // No warnings or errors to flush; we can bail out early here too .
1247
1264
return ;
1248
1265
}
1249
1266
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
1259
-
1260
- // Fill in the rest of the operations.
1267
+ // We can create a smaller operations array than flushPendingEvents()
1268
+ // because we only need to flush warning and error counts.
1269
+ // Only a few pieces of fixed information are required up front.
1270
+ const operations : OperationsArray = new Array (
1271
+ 3 + pendingOperations . length ,
1272
+ ) ;
1273
+ operations [ 0 ] = rendererID ;
1274
+ operations [ 1 ] = currentRootID ;
1275
+ operations [ 2 ] = 0 ; // String table size
1261
1276
for ( let j = 0 ; j < pendingOperations . length ; j ++ ) {
1262
- operations [ i + j ] = pendingOperations [ j ] ;
1277
+ operations [ 3 + j ] = pendingOperations [ j ] ;
1263
1278
}
1264
1279
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
- }
1280
+ flushOrQueueOperations ( operations ) ;
1277
1281
1278
1282
pendingOperations . length = 0 ;
1279
1283
} , 1000 ) ;
@@ -1291,10 +1295,7 @@ export function attach(
1291
1295
}
1292
1296
1293
1297
function recordPendingErrorsAndWarnings ( ) {
1294
- if ( flushPendingErrorsAndWarningsAfterDelayTimeoutID !== null ) {
1295
- clearTimeout ( flushPendingErrorsAndWarningsAfterDelayTimeoutID ) ;
1296
- flushPendingErrorsAndWarningsAfterDelayTimeoutID = null ;
1297
- }
1298
+ clearPendingErrorsAndWarningsAfterDelay ( ) ;
1298
1299
1299
1300
fibersWithChangedErrorOrWarningCounts . forEach ( fiberID => {
1300
1301
const fiber = idToFiberMap . get ( fiberID ) ;
@@ -1385,7 +1386,7 @@ export function attach(
1385
1386
// Which in turn enables fiber props, states, and hooks to be inspected.
1386
1387
let i = 0 ;
1387
1388
operations [ i ++ ] = rendererID ;
1388
- operations [ i ++ ] = currentRootID ; // Use this ID in case the root was unmounted!
1389
+ operations [ i ++ ] = currentRootID ;
1389
1390
1390
1391
// Now fill in the string table.
1391
1392
// [stringTableLength, str1Length, ...str1, str2Length, ...str2, ...]
@@ -1432,18 +1433,9 @@ export function attach(
1432
1433
i += pendingOperations . length ;
1433
1434
1434
1435
// 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
- }
1436
+ flushOrQueueOperations ( operations ) ;
1446
1437
1438
+ // Reset all of the pending state now that we've told the frontend about it.
1447
1439
pendingOperations . length = 0 ;
1448
1440
pendingRealUnmountedIDs . length = 0 ;
1449
1441
pendingSimulatedUnmountedIDs . length = 0 ;
0 commit comments