Skip to content

Commit 2c8a145

Browse files
authored
Fix ignored setState in Safari when iframe is touched (#24459)
1 parent 6266263 commit 2c8a145

3 files changed

Lines changed: 47 additions & 12 deletions

File tree

‎packages/react-dom/src/__tests__/ReactDOMSafariMicrotaskBug-test.js‎

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ let act;
1616

1717
describe('ReactDOMSafariMicrotaskBug-test',()=>{
1818
letcontainer;
19-
letsimulateSafariBug;
19+
letflushMicrotasksPrematurely;
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+
constprevQueue=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
letran=false;
5053
functionFoo(){
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+
functionFoo(){
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+
constroot=ReactDOMClient.createRoot(container);
89+
awaitact(async()=>{
90+
root.render(<Foo/>);
91+
});
92+
expect(container.textContent).toBe('0');
93+
awaitact(async()=>{
94+
container.firstChild.dispatchEvent(
95+
newMouseEvent('click',{bubbles: true}),
96+
);
97+
});
98+
expect(container.textContent).toBe('1');
99+
});
71100
});

‎packages/react-reconciler/src/ReactFiberWorkLoop.new.js‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -835,9 +835,12 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {
835835
// https://github.com/facebook/react/issues/22459
836836
// We don't support running callbacks in the middle of render
837837
// or commit so we need to check against that.
838-
if(executionContext===NoContext){
839-
// It's only safe to do this conditionally because we always
840-
// check for pending work before we exit the task.
838+
if(
839+
(executionContext&(RenderContext|CommitContext))===
840+
NoContext
841+
){
842+
// Note that this would still prematurely flush the callbacks
843+
// if this happens outside render or commit phase (e.g. in an event).
841844
flushSyncCallbacks();
842845
}
843846
});

‎packages/react-reconciler/src/ReactFiberWorkLoop.old.js‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -835,9 +835,12 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {
835835
// https://github.com/facebook/react/issues/22459
836836
// We don't support running callbacks in the middle of render
837837
// or commit so we need to check against that.
838-
if(executionContext===NoContext){
839-
// It's only safe to do this conditionally because we always
840-
// check for pending work before we exit the task.
838+
if(
839+
(executionContext&(RenderContext|CommitContext))===
840+
NoContext
841+
){
842+
// Note that this would still prematurely flush the callbacks
843+
// if this happens outside render or commit phase (e.g. in an event).
841844
flushSyncCallbacks();
842845
}
843846
});

0 commit comments

Comments
 (0)