Fix stale anchor preserved when clearing transient nodes#14251
Fix stale anchor preserved when clearing transient nodes#14251lukasmasuch merged 2 commits intodevelopfrom
Conversation
When a transient node (spinner) captured an element from a previous run as its anchor, and the transient was cleared, the anchor was restored directly without checking if it was stale. This caused UI elements from previous runs to incorrectly persist after spinner completion. The fix checks if the anchor is stale before restoring it by calling `node.anchor.accept(this)` instead of returning `node.anchor` directly. Closes #14249
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
✅ PR preview is ready!
|
There was a problem hiding this comment.
Pull request overview
Fixes a frontend render-tree regression where clearing a transient node (e.g., spinner) could restore an anchor element from a previous script run without re-checking whether that anchor is stale, causing unexpected “old” UI content to reappear.
Changes:
- Update
ClearStaleNodeVisitor.visitTransientNodeto restore a cleared transient’s anchor viaanchor.accept(this)so the anchor is also filtered for staleness. - Adjust and extend unit tests to cover the “cleared transient with stale anchor” scenario.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| frontend/lib/src/render-tree/visitors/ClearStaleNodeVisitor.ts | Ensures restored transient anchors are also visited/filtered for staleness before being returned. |
| frontend/lib/src/render-tree/visitors/ClearStaleNodeVisitor.test.ts | Updates the existing “restore anchor” test and adds coverage for stale-anchor restoration returning undefined. |
SummaryThis PR fixes a regression (from #13849) where clearing a transient node (e.g., a spinner) could restore a stale anchor element from a previous script run. The root cause was that Files changed (2):
Code QualityReviewers agreed unanimously: The fix is minimal, surgical, and idiomatic. It leverages the existing visitor pattern — The added comments at lines 144-147 clearly explain the non-obvious reasoning for why the anchor must be checked for staleness, which both reviewers found appropriate. Test CoverageReviewers agreed that the unit test changes are well-structured:
Minor point of divergence on E2E coverage: One reviewer (gpt-5.3-codex-high) suggested an optional follow-up E2E test, while the other (opus-4.6-thinking) noted existing E2E coverage. Verification confirms that Backwards CompatibilityReviewers agreed: Fully backwards compatible. The previous behavior (returning stale anchors) was a bug, not a feature. No API changes, no protobuf changes, and no changes to the public Security & RiskReviewers agreed: No security concerns. The change is entirely within the frontend render tree visitor logic and does not touch WebSocket handling, authentication, session management, file operations, CORS, or any external-facing surface. Regression risk is low and localized. External test recommendation
AccessibilityReviewers agreed: No UI changes, no new components, no DOM structure modifications. Accessibility is not impacted. RecommendationsNo blocking changes requested by either reviewer. The only suggestion was an optional E2E follow-up (gpt-5.3-codex-high), which was resolved by confirming existing E2E coverage already addresses the scenario. Missing ReviewsAll expected models submitted reviews:
VerdictAPPROVED: Both reviewers unanimously approved. The fix is a clean, minimal one-line change that correctly addresses a regression in transient node staleness checking, with proper unit test coverage and existing E2E coverage for the user-facing scenario. No blocking quality, compatibility, or security concerns were raised. This is a consolidated AI review by 📋 Review by `gpt-5.3-codex-high`SummaryThis PR fixes a regression where clearing a transient node (for example, a spinner) could restore a stale anchor element from a previous script run. The core change in Code QualityThe implementation is minimal and targeted, with good locality and clear intent:
No maintainability or pattern concerns found. Test CoverageUnit coverage for the modified behavior is good:
E2E coverage was not added in this PR. Given the change is in internal render-tree stale filtering and is now directly unit-tested at the decision point, this is acceptable; residual risk is low but non-zero for full UI flow interactions. Backwards CompatibilityNo public API changes or protocol changes were introduced. The behavior change is corrective (removing stale UI artifacts) and should be backwards compatible for users relying on expected rerun semantics. Security & RiskNo security-sensitive surfaces were modified (no auth/session, transport, routing, storage, CSP/CORS, upload/asset handling, or dynamic code execution changes). Regression risk appears low and localized to transient-node cleanup behavior. External test recommendation
AccessibilityNo UI component markup, keyboard interaction, ARIA semantics, or focus behavior changed. No accessibility concerns identified. Recommendations
VerdictAPPROVED: The fix addresses the reported root cause with targeted code and solid unit regression coverage, with no blocking quality, compatibility, or security concerns. This is an automated AI review by 📋 Review by `opus-4.6-thinking`SummaryThis PR fixes a regression introduced in #13849 where stale elements from previous script runs could persist after spinner (transient node) completion. The root cause was that Only two files are changed:
Code QualityThe fix is minimal, surgical, and idiomatic. It leverages the existing visitor pattern — The updated comments at lines 144-147 of The test changes are well-structured:
Test CoverageUnit tests: The new test at line 281-295 directly covers the regression scenario. Together with the corrected existing test, both positive (current anchor restored) and negative (stale anchor filtered) paths are covered for the early-return branch. E2E tests: The existing E2E test The test coverage is adequate for this change. Backwards CompatibilityThis change is fully backwards compatible. The previous behavior (returning stale anchors) was a bug, not a feature. There are no API changes, no protobuf changes, and no changes to the public Security & RiskNo security concerns. The change is entirely within the frontend render tree visitor logic and does not touch:
Regression risk is low. The External test recommendation
AccessibilityNo UI changes, no new components, and no DOM structure modifications. This fix only affects which render tree nodes survive the stale-clearing pass. Accessibility is not impacted. RecommendationsNo changes requested. The fix is correct, minimal, well-tested, and follows existing patterns. VerdictAPPROVED: A clean, minimal one-line fix for a regression in transient node staleness checking, with proper unit test coverage and existing E2E test coverage for the user-facing scenario. This is an automated AI review by |
Add unit test to verify that a stale anchor without fragmentId is preserved during a fragment run when the transient node is cleared. This addresses a review comment requesting explicit coverage for the fragment-run edge case to prevent regressions.
SummaryThis PR fixes a regression (from #13849) in transient-node cleanup where stale elements from previous script runs could persist after spinner completion. The root cause was in The change is a single-line fix in Reviewer agreement: Both Code QualityThe fix is minimal, precise, and follows the established visitor pattern. Replacing Both reviewers confirmed no code quality issues. No disagreements. Test CoverageUnit coverage is strong and well-targeted:
Both reviewers noted the absence of an e2e test for the exact reproduction scenario from #14249 (segmented control + cached function with spinner + tabs). Both agreed this is acceptable given the direct unit-level coverage of the buggy code path, and recommended it as an optional future hardening step. Backwards CompatibilityNo public API or protocol changes. The behavior change is corrective: stale anchors that were previously (incorrectly) retained are now filtered out, aligning with expected stale-node semantics. Both reviewers agreed this is fully backwards compatible. Security & RiskNo security-sensitive surfaces were modified. The change is entirely within frontend render-tree visitor logic — no auth, session, websocket, routing, CORS/CSP/XSRF, file handling, or external service paths were touched. Regression risk is low due to the minimal logic delta and targeted unit tests. Both reviewers agreed. No disagreements. External test recommendation
Both reviewers agreed. No disagreements. AccessibilityNo accessibility impact. The change only affects which elements are included in or excluded from the render tree (stale element cleanup). No UI components, ARIA attributes, focus management, or keyboard handling were modified. Both reviewers agreed. No disagreements. Reviewer Consensus
Missing reviews: None. Both expected models ( Recommendations
VerdictAPPROVED: Both reviewers unanimously approved. The fix is a clean, minimal one-line change that correctly applies staleness checking to transient node anchors, with well-targeted unit tests covering the fix and relevant edge cases. No blocking or critical issues were raised. This is a consolidated AI review by 📋 Review by `gpt-5.3-codex-high`SummaryThis PR fixes a stale-render regression in transient-node cleanup by ensuring a cleared transient's anchor is also passed through stale-node filtering before restoration. The implementation change in Code QualityThe code change is precise and follows existing visitor patterns: replacing direct anchor return with No code quality issues were identified. Test CoverageUnit coverage is strong for this fix:
No e2e tests were added. Given the tightly scoped render-tree visitor logic and direct unit-level regression coverage, this is acceptable for this PR, though a future user-flow e2e around spinner clear behavior could further harden against integration regressions. Backwards CompatibilityNo public API or protocol changes are introduced. Behavior change is corrective: stale anchors that were previously (incorrectly) retained are now filtered, aligning with expected stale-node semantics. This should be backwards compatible for users and reduces unintended stale UI persistence. Security & RiskNo security-sensitive surfaces were modified (no auth/session, websocket transport, routing, cookies/XSRF, asset serving, external networking, or dynamic code execution changes). Regression risk appears low due to:
External test recommendation
AccessibilityNo accessibility-impacting UI markup, interaction handlers, semantics, focus behavior, or styling were changed. A11y risk is effectively none for this PR scope. Recommendations
VerdictAPPROVED: The fix is targeted, regression-tested at unit level, low risk, and ready to merge. This is an automated AI review by 📋 Review by `opus-4.6-thinking`SummaryThis PR fixes a regression introduced in #13849 where stale elements from previous script runs could persist after spinner (transient node) completion. The root cause was in The change is a single-line fix in Code QualityThe fix is minimal, precise, and follows the established visitor pattern already used elsewhere in the same file. Specifically:
The pre-existing test ("restores anchor for transient cleared in current run") was correctly updated to use Test CoverageUnit tests are good and cover the critical code paths:
E2E test coverage: While the existing Backwards CompatibilityThis change is fully backwards compatible. The previous behavior was a bug — stale elements were unintentionally preserved. Users affected by the regression (#14249) will see the correct behavior restored: elements from previous script runs will no longer "leak through" after spinner completion. There is no API surface change. Security & RiskNo security concerns. The change is entirely within frontend render-tree visitor logic. It does not touch:
Regression risk is low. The fix makes the early-return path consistent with the general path that already calls External test recommendationRecommendation: No —
AccessibilityNo accessibility impact. The change only affects which elements are included in or excluded from the render tree (stale element cleanup). It does not modify any UI components, ARIA attributes, focus management, or keyboard handling. RecommendationsNo blocking issues. One minor suggestion:
VerdictAPPROVED: Clean, minimal one-line bug fix that correctly applies staleness checking to transient node anchors, with well-targeted unit tests covering the fix and relevant edge cases. This is an automated AI review by |
kmcgrady
left a comment
There was a problem hiding this comment.
The change feels reasonable. Perhaps we can confirm with the user. If there's anyway the AI could have caught this better, that would be great.
|
Checked it with the problematic issue.
Maybe with a bit more "architectural" information on how the frontend tree rendering works. But not sure if this would have caught it |
Describe your changes
Fixes a regression introduced in #13849 where stale elements from previous script runs could persist after spinner completion.
Root cause: When a transient node (spinner) captured an element from a previous run as its anchor, and the transient was cleared, the anchor was restored directly without checking if it was stale.
The fix: Change
return node.anchortoreturn node.anchor.accept(this)so the anchor is also checked for staleness before being restored.GitHub Issue Link (if applicable)
Closes #14249
Testing Plan
Agent metrics