fix: use microtask queue for whatwg-fetch XHR events#94399
Conversation
Replaces `setTimeout(0)` with `queueMicrotask` for XHR event handlers within the `whatwg-fetch` polyfill.
|
|
|
@rohit9625 I think we should address the "Not Found" page bug mentioned here as well: #90309 (comment). This bug could block QA from testing the fix. |
|
Well, I can fix that bug too. Let me check if we have existing tickets for this bug :) |
|
I didn't find any existing GitHub issues for that Not Here page bug. Also, I can reproduce that on the web target only. So, are you sure that we should fix that issue in the same PR, @dmkt9? |
|
@rohit9625 Yes. Although it has a different root cause, the reproduction steps are the same as the original bug, so I think it should be addressed in this PR as well. Additionally, I can reproduce it on Android and iOS as well. |
Okay, working on the fix now.
Strange, I can only reproduce it on the web (wide-layout) because that uses a different component and it was not reproducible for narrow layout. I'm fixing the issue on web and I think it will fix it on other platforms as well. |
Thanks.
Can you try reproducing it on the Report page? 2026-06-25.17-50-10.mp4 |
|
Sorry, it took a bit building the Android app and yes, it is reproducible via Spend -> Reports page. Could you please confirm the expected behavior here? |
|
@rohit9625 I think we don't need to handle that bug ourselves, since we already have a similar issue tracked here: #91917 |
|
Ohh, I missed that issue. Yeah, you're right we don't need to fix that issue in this PR right now. So, are we good to go with merging this PR, @dmkt9? |
|
The reason I think that the Not Here page issue will not block testing this PR is that the current issue is about infinite loading, which is resolved by this PR. The Not Here page will be visible for a moment if online, and that too via the Spend -> Reports flow. |
|
@rohit9625 From my testing, this PR looks good. However, just to be safe, could you merge the latest |
|
I've merged the main branch, @dmkt9. Please trigger an Adhoc build, I also want to test on Adhoc build because locally its very laggy sometimes. |
|
Thanks. I'll ask someone to help trigger it. |
|
Hi @dmkt9, did you ask somebody? If appropriate, I can drop a message on Slack for this :) |
Yes. I did |
|
🚧 puneetlath has triggered a test Expensify/App build. You can view the workflow run here. |
This comment has been minimized.
This comment has been minimized.
|
@puneetlath Could you please re-trigger the build? I noticed the Android build failed |
|
Hi @puneetlath, Friendly bump on the above comment! |
|
Triggered again! |
|
🚧 puneetlath has triggered a test Expensify/App build. You can view the workflow run here. |
This comment has been minimized.
This comment has been minimized.
|
Just tested the Adhoc Android build and it works as expected :) |
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppandroid.hybrid.mp4Android: mWeb Chromeandroid.chrome.mp4iOS: HybridAppios.hybrid.mp4iOS: mWeb Safariios.safari.mp4MacOS: Chrome / Safarimac.safari.mp4 |
dmkt9
left a comment
There was a problem hiding this comment.
LGTM.
Since our fetch implementation now uses a microtask, I was a bit concerned that it might block the JS thread if there were a large number of requests in the network queue. However, I thought the risk was low because fetch itself is not a microtask, so we shouldn't end up with a long chain of microtasks.
To be safe, I tested it on an ad hoc build, and everything worked as expected without any noticeable impact.
|
Hi @puneetlath, we are waiting for you to review the PR :) |
|
Friendly bump! @puneetlath :) |
|
🚧 puneetlath has triggered a test Expensify/App build. You can view the workflow run here. |
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
🚀 Deployed to staging by https://github.com/puneetlath in version: 9.4.28-0 🚀
|
|
🚀 Deployed to production by https://github.com/mountiny in version: 9.4.28-2 🚀
Bundle Size Analysis (Sentry): |
Explanation of Change
In React Native (iOS), we observed cases where:
xhr.onloadexecuted successfully.Because the promise resolution depends on a timer, any environment-specific issue affecting timer delivery can prevent completed requests from resolving promptly.
So this PR replaces
setTimeout(0)withqueueMicrotaskfor XHR event handlers within thewhatwg-fetchpolyfill.Why
queueMicrotask? : Microtasks are generally executed as part of the current JavaScript turn after the current call stack unwinds and do not depend on timer infrastructure. Also, I don't see any benefit of usingsetTimeouthere because we are passing0as a timeout that is supposed to be executed as soon as possible. So, we should better usequeueMicrotaskhere.Fixed Issues
$ #90309
PROPOSAL: $ #90309 (comment)
Tests
Offline tests
QA Steps
// TODO: These must be filled out, or the issue title must include "[No QA]."
Same as tests
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)Avatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Screen.Recording.2026-06-24.at.9.15.44.AM.mov
Android: mWeb Chrome
Screen.Recording.2026-06-24.at.8.30.50.AM.mov
iOS: Native
Screen.Recording.2026-06-24.at.8.49.51.AM.mov
iOS: mWeb Safari
Screen.Recording.2026-06-24.at.8.41.16.AM.mov
MacOS: Chrome / Safari
Screen.Recording.2026-06-24.at.8.21.36.AM.mov