@@ -16,7 +16,7 @@ let act;
1616
1717describe ( 'ReactDOMSafariMicrotaskBug-test' , ( ) => {
1818let container ;
19- let simulateSafariBug ;
19+ let flushMicrotasksPrematurely ;
2020
2121beforeEach ( ( ) => {
2222// In Safari, microtasks don't always run on clean stack.
@@ -27,9 +27,12 @@ describe('ReactDOMSafariMicrotaskBug-test', () => {
2727window . queueMicrotask = function ( cb ) {
2828queue . 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
3538jest . resetModules ( ) ;
@@ -45,7 +48,7 @@ describe('ReactDOMSafariMicrotaskBug-test', () => {
4548document . 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 ( ) => {
4952let ran = false ;
5053function Foo ( ) {
5154const [ state , setState ] = React . useState ( 0 ) ;
@@ -55,7 +58,7 @@ describe('ReactDOMSafariMicrotaskBug-test', () => {
5558if ( ! ran ) {
5659ran = true ;
5760setState ( 1 ) ;
58- simulateSafariBug ( ) ;
61+ flushMicrotasksPrematurely ( ) ;
5962}
6063} } >
6164{ state }
@@ -68,4 +71,30 @@ describe('ReactDOMSafariMicrotaskBug-test', () => {
6871} ) ;
6972expect ( 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