@@ -19,8 +19,6 @@ import type {
19
19
} from 'react-devtools-shared/src/backend/types' ;
20
20
import type { StyleAndLayout as StyleAndLayoutPayload } from 'react-devtools-shared/src/backend/NativeStyleEditor/types' ;
21
21
22
- const BATCH_DURATION = 100 ;
23
-
24
22
// This message specifies the version of the DevTools protocol currently supported by the backend,
25
23
// as well as the earliest NPM version (e.g. "4.13.0") that protocol is supported by on the frontend.
26
24
// This enables an older frontend to display an upgrade message to users for a newer, unsupported backend.
@@ -276,7 +274,7 @@ class Bridge<
276
274
} > {
277
275
_isShutdown : boolean = false ;
278
276
_messageQueue : Array < any > = [ ] ;
279
- _timeoutID : TimeoutID | null = null ;
277
+ _scheduledFlush : boolean = false ;
280
278
_wall : Wall ;
281
279
_wallUnlisten : Function | null = null ;
282
280
@@ -324,8 +322,19 @@ class Bridge<
324
322
// (or we're waiting for our setTimeout-0 to fire), then _timeoutID will
325
323
// be set, and we'll simply add to the queue and wait for that
326
324
this._messageQueue.push(event, payload);
327
- if (!this._timeoutID) {
328
- this . _timeoutID = setTimeout ( this . _flush , 0 ) ;
325
+ if (!this._scheduledFlush) {
326
+ this . _scheduledFlush = true ;
327
+ // $FlowFixMe
328
+ if ( typeof devtoolsJestTestScheduler === 'function' ) {
329
+ // This exists just for our own jest tests.
330
+ // They're written in such a way that we can neither mock queueMicrotask
331
+ // because then we break React DOM and we can't not mock it because then
332
+ // we can't synchronously flush it. So they need to be rewritten.
333
+ // $FlowFixMe
334
+ devtoolsJestTestScheduler ( this . _flush ) ; // eslint-disable-line no-undef
335
+ } else {
336
+ queueMicrotask ( this . _flush ) ;
337
+ }
329
338
}
330
339
}
331
340
@@ -363,34 +372,23 @@ class Bridge<
363
372
do {
364
373
this . _flush ( ) ;
365
374
} while (this._messageQueue.length);
366
-
367
- // Make sure once again that there is no dangling timer.
368
- if (this._timeoutID !== null) {
369
- clearTimeout ( this . _timeoutID ) ;
370
- this . _timeoutID = null ;
371
- }
372
375
}
373
376
374
377
_flush : ( ) => void = ( ) => {
375
378
// This method is used after the bridge is marked as destroyed in shutdown sequence,
376
379
// so we do not bail out if the bridge marked as destroyed.
377
380
// It is a private method that the bridge ensures is only called at the right times.
378
-
379
- if ( this . _timeoutID !== null ) {
380
- clearTimeout ( this . _timeoutID ) ;
381
- this . _timeoutID = null ;
382
- }
383
-
384
- if (this._messageQueue.length) {
385
- for ( let i = 0 ; i < this . _messageQueue . length ; i += 2 ) {
386
- this . _wall . send ( this . _messageQueue [ i ] , ...this . _messageQueue [ i + 1 ] ) ;
381
+ try {
382
+ if ( this . _messageQueue . length ) {
383
+ for ( let i = 0 ; i < this . _messageQueue . length ; i += 2 ) {
384
+ this . _wall . send ( this . _messageQueue [ i ] , ...this . _messageQueue [ i + 1 ] ) ;
385
+ }
386
+ this . _messageQueue . length = 0 ;
387
387
}
388
- this._messageQueue.length = 0;
389
-
390
- // Check again for queued messages in BATCH_DURATION ms. This will keep
391
- // flushing in a loop as long as messages continue to be added. Once no
392
- // more are, the timer expires.
393
- this._timeoutID = setTimeout(this._flush, BATCH_DURATION);
388
+ } finally {
389
+ // We set this at the end in case new messages are added synchronously above.
390
+ // They're already handled so they shouldn't queue more flushes.
391
+ this . _scheduledFlush = false ;
394
392
}
395
393
} ;
396
394
0 commit comments