fix(agent): RenderRepaintBoundary screenshot for iOS/Impeller#108
Merged
Conversation
OffsetLayer.toImage() returns a GPU-backed texture on Impeller (Flutter 3.10+ default on iOS) where image.toByteData(png) returns null, causing a null assertion crash. RenderRepaintBoundary.toImage() is the Impeller-safe path. New strategy: - endOfFrame wait before capture to ensure latest frame is rendered - Primary: walk element tree for largest RenderRepaintBoundary (Impeller-safe) - Fallback: OffsetLayer.toImage() (Skia compatibility, pre-3.10 builds) - Null-safe: no more ! assertion on bytes, surfaces as a ProbeError instead
Adds the probe_agent CHANGELOG entry (CI was blocking the merge of #108 because probe_agent/lib/ changed without a matching CHANGELOG update), bumps all package versions from 0.9.4 to 0.9.5, and adds the matching 0.9.5 entries to the root CHANGELOG, wiki Home.md, mcp.md verify snippet, and per-package CHANGELOGs. The Dart agent code fix itself is in commit a595343 (already on this PR branch): - Primary capture via the largest visible RenderRepaintBoundary, which Impeller supports natively (vs OffsetLayer.toImage which returns a GPU texture on Impeller and yields null PNG bytes). - Fallback to OffsetLayer.toImage when no boundary is found (Skia). - Awaits WidgetsBinding.instance.endOfFrame before capture. - Uses View.devicePixelRatio instead of hardcoded 2.0. Verified: go test ./... 16/16 packages pass staticcheck ./... zero issues dart analyze probe_agent/lib no issues found
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On Flutter 3.10+ with Impeller (the default renderer on iOS),
OffsetLayer.toImage()returns a GPU-backed texture. Callingimage.toByteData(format: png)on a GPU texture returnsnullin Impeller, which hit thebytes!null assertion in_screenshot()and crashed.Result: all
take screenshotsteps andon failureauto-screenshots silently failed (or threw) on any iOS simulator running Flutter 3.10+.Fix
RenderRepaintBoundary.toImage()is explicitly supported by Impeller — it triggers a readback from the GPU texture to CPU memory. Strategy:await endOfFramebefore capture so the latest rendered frame is visibleRenderRepaintBoundary(Impeller-safe)OffsetLayer.toImage()(Skia, pre-3.10 builds)ProbeErrorinstead of assertion crashTesting
dart analyze lib/src/executor.dart— no issuesflutter test— 13/13 pass