Skip to content

Commit d9f8189

Browse files
kblokclaude
andcommitted
fix: avoid premature context cancellation when navigation returns a value
Replace the SetContext-based NotifyDestroyed call (which raced with async response processing) with a Frame.FrameNavigated subscription. Chrome sends callFunctionOn responses before Page.frameNavigated, so signalling destruction from FrameNavigated guarantees valid return values are already resolved before cancellation fires. Fixes ShouldNotThrowAnErrorWhenEvaluationDoesANavigation hang introduced by the previous context-destruction fix. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 19d0863 commit d9f8189

1 file changed

Lines changed: 19 additions & 6 deletions

File tree

lib/PuppeteerSharp/IsolatedWorld.cs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ public IsolatedWorld(
4747

4848
_detached = false;
4949
FrameUpdated();
50+
51+
if (Frame != null)
52+
{
53+
Frame.FrameNavigated += Frame_FrameNavigated;
54+
}
5055
}
5156

5257
/// <inheritdoc/>
@@ -211,6 +216,12 @@ internal void Detach()
211216
{
212217
_detached = true;
213218
Client.MessageReceived -= Client_MessageReceived;
219+
220+
if (Frame != null)
221+
{
222+
Frame.FrameNavigated -= Frame_FrameNavigated;
223+
}
224+
214225
TaskManager.TerminateAll(new PuppeteerException("waitForFunction failed: frame got detached."));
215226
}
216227

@@ -286,18 +297,20 @@ internal void SetContext(ExecutionContext context)
286297
throw new ArgumentNullException(nameof(context));
287298
}
288299

289-
// Cancel any pending evaluations on the old context before replacing it.
290-
// This handles the edge case where a new context arrives without an explicit
291-
// executionContextsCleared/Destroyed event (e.g., Chrome reusing a context ID).
292-
var oldContext = _context;
293300
_context = context;
294-
oldContext?.NotifyDestroyed();
295-
296301
_contextBindings.Clear();
297302
_contextResolveTaskWrapper.TrySetResult(context);
298303
TaskManager.RerunAll();
299304
}
300305

306+
private void Frame_FrameNavigated(object sender, FrameNavigatedEventArgs e)
307+
{
308+
if (!e.NavigatedWithinDocument)
309+
{
310+
_context?.NotifyDestroyed();
311+
}
312+
}
313+
301314
private async void Client_MessageReceived(object sender, MessageEventArgs e)
302315
{
303316
try

0 commit comments

Comments
 (0)