@@ -16,7 +16,7 @@ let act;
1616
1717describe ( 'ReactDOMSafariMicrotaskBug-test' , ( ) => {
1818 let container ;
19- let simulateSafariBug ;
19+ let flushMicrotasksPrematurely ;
2020
2121 beforeEach ( ( ) => {
2222 // In Safari, microtasks don't always run on clean stack.
@@ -27,9 +27,12 @@ describe('ReactDOMSafariMicrotaskBug-test', () => {
2727 window . queueMicrotask = function ( cb ) {
2828 queue . push ( cb ) ;
2929 } ;
30- simulateSafariBug = function ( ) {
31- queue . forEach ( cb => cb ( ) ) ;
32- queue = [ ] ;
30+ flushMicrotasksPrematurely = function ( ) {
31+ while ( queue . length > 0 ) {
32+ const prevQueue = queue ;
33+ queue = [ ] ;
34+ prevQueue . forEach ( cb => cb ( ) ) ;
35+ }
3336 } ;
3437
3538 jest . resetModules ( ) ;
@@ -45,7 +48,7 @@ describe('ReactDOMSafariMicrotaskBug-test', () => {
4548 document . body . removeChild ( container ) ;
4649 } ) ;
4750
48- it ( 'should be resilient to buggy queueMicrotask ' , async ( ) => {
51+ it ( 'should deal with premature microtask in commit phase ' , async ( ) => {
4952 let ran = false ;
5053 function Foo ( ) {
5154 const [ state , setState ] = React . useState ( 0 ) ;
@@ -55,7 +58,7 @@ describe('ReactDOMSafariMicrotaskBug-test', () => {
5558 if ( ! ran ) {
5659 ran = true ;
5760 setState ( 1 ) ;
58- simulateSafariBug ( ) ;
61+ flushMicrotasksPrematurely ( ) ;
5962 }
6063 } } >
6164 { state }
@@ -68,4 +71,30 @@ describe('ReactDOMSafariMicrotaskBug-test', () => {
6871 } ) ;
6972 expect ( container . textContent ) . toBe ( '1' ) ;
7073 } ) ;
74+
75+ it ( 'should deal with premature microtask in event handler' , async ( ) => {
76+ function Foo ( ) {
77+ const [ state , setState ] = React . useState ( 0 ) ;
78+ return (
79+ < button
80+ onClick = { ( ) => {
81+ setState ( 1 ) ;
82+ flushMicrotasksPrematurely ( ) ;
83+ } } >
84+ { state }
85+ </ button >
86+ ) ;
87+ }
88+ const root = ReactDOMClient . createRoot ( container ) ;
89+ await act ( async ( ) => {
90+ root . render ( < Foo /> ) ;
91+ } ) ;
92+ expect ( container . textContent ) . toBe ( '0' ) ;
93+ await act ( async ( ) => {
94+ container . firstChild . dispatchEvent (
95+ new MouseEvent ( 'click' , { bubbles : true } ) ,
96+ ) ;
97+ } ) ;
98+ expect ( container . textContent ) . toBe ( '1' ) ;
99+ } ) ;
71100} ) ;
0 commit comments