Fix race-conditions in resolving#668
Conversation
1) Clear pending callbacks before running them, so re-entrant hidden-page flushes can’t replay the same callback and overflow the stack. 2) Keep draining callbacks added during a hidden/pagehide flush, so work queued while the tab is hidden doesn’t get stuck behind a rAF that may never run. 3) Skip stale scheduled rAF/timeout continuations after a lifecycle flush already ran their callback. 4) Clear batched rAF callbacks before invoking them, so callbacks queued during a rAF drain are scheduled for the next frame instead of mutating the active iteration. 5) Run callbacks immediately if the tab becomes hidden while waiting for load, instead of scheduling rAF work in a hidden tab. 6) Rename pendingResolvers to pendingCallbacks, since this script stores synchronous work callbacks, not Promise resolvers. 7) Replace persistent __f mutation for history/submit wrappers with invocation-scoped tracking, so native methods run once per override chain without corrupting repeated calls.
There was a problem hiding this comment.
Pull request overview
This PR hardens the 3rd-party-optimizer plugin’s yielding/flush logic to prevent re-entrancy and stale continuation issues when the page becomes hidden/unloaded, reducing the risk of stuck work and stack overflows during lifecycle transitions.
Changes:
- Reworks pending work tracking from “resolvers” to “callbacks” and updates flush/drain behavior (including clearing before invoking and skipping stale scheduled continuations).
- Refactors history/submit override chain handling to avoid persistent marker mutation and ensure native methods aren’t re-invoked within an override chain.
- Updates documentation and bumps the plugin version.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| plugins/3rd-party-optimizer/yieldGTMCalls.md | Updates the implementation notes for GTM yielding behavior. |
| plugins/3rd-party-optimizer/src/yieldGTMCalls.ts | Fixes race conditions in callback draining/scheduling and refactors override-chain tracking. |
| plugins/3rd-party-optimizer/package.json | Bumps plugin version to 1.0.3. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 79d2ad30d9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
c8a294f to
e7d47d2
Compare
e7d47d2 to
b5098e2
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b5098e28e9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 55abc7852c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Description
This pull request fixes a few race-conditions in the 3rd-party-optimizer plugin.
Clear pending callbacks before running them, so re-entrant hidden-page flushes can’t replay the same callback and overflow the stack.
Keep draining callbacks added during a hidden/pagehide flush, so work queued while the tab is hidden doesn’t get stuck behind a rAF that may never run.
Skip stale scheduled rAF/timeout continuations after a lifecycle flush already ran their callback.
Clear batched rAF callbacks before invoking them, so callbacks queued during a rAF drain are scheduled for the next frame instead of mutating the active iteration.
Run callbacks immediately if the tab becomes hidden while waiting for load, instead of scheduling rAF work in a hidden tab.
Rename pendingResolvers to pendingCallbacks, since this script stores synchronous work callbacks, not Promise resolvers.
Replace persistent __f mutation for history/submit wrappers with invocation-scoped tracking, so native methods run once per override chain without corrupting repeated calls.
Changelog
Testing