Skip to content

[vector_graphics] Catch any throwable in useHtmlRenderObject() and cache HTML fallback - #13545

Merged
auto-submit[bot] merged 6 commits into
flutter:mainfrom
harryterkelsen:vector-graphics-catch-any-throwable-in
Nov 11, 2026
Merged

auto-submit[bot] merged 6 commits into
flutter:mainfrom
harryterkelsen:vector-graphics-catch-any-throwable-in

Conversation

@harryterkelsen

Copy link
Copy Markdown
Contributor

In Flutter Web under the CanvasKit and WebAssembly renderers, vector graphics determine whether to use native raster rendering (_RawVectorGraphicWidget) or an HTML compatibility renderer (_RawWebVectorGraphicWidget) by calling useHtmlRenderObject(), which probes runtime support by recording a 1x1 ui.Picture and invoking picture.toImageSync(1, 1).

Previously, useHtmlRenderObject() caught only a narrow allow-list of exception types (UnsupportedError, StateError, and NoSuchMethodError). When WebGL surface creation or OffscreenCanvas initialization fails mid-session, CanvasKit and browser environments can throw unhandled throwables such as bare JavaScript strings ('Canvas with id [object OffscreenCanvas] was not found'), foreign JS errors, or null. Because these were unhandled, VectorGraphic widgets crashed, and because useHtmlRenderObject() is evaluated in a static field initializer, subsequent widget builds re-evaluated the uninitialized field and re-threw continuously. Furthermore, _cachedUseHtmlRenderObject remained null on failure, preventing the HTML fallback from ever being recorded.

This PR updates useHtmlRenderObject() to catch any throwable using a bare catch (_) block, sets _cachedUseHtmlRenderObject = true on any failure, ensures ui.Picture and ui.Image resources are always disposed in finally, and adds unit tests covering five distinct failure modes, success path caching, and reset lifecycle transitions.

Fixes flutter/flutter#189451

Behavioral Changes

  • Before: When picture.toImageSync(1, 1) threw non-Dart errors (such as bare JavaScript strings or foreign JS errors during WebGL/canvas failures), the throwable escaped unhandled from useHtmlRenderObject(), crashing VectorGraphic widget build passes and re-throwing repeatedly without caching a fallback.
  • After: Any throwable thrown during toImageSync(1, 1) is caught, causing useHtmlRenderObject() to return true (selecting the HTML compatibility render object) and permanently cache _cachedUseHtmlRenderObject = true so subsequent widget builds reuse the fallback without re-triggering the failing probe.

Where to focus

  • Key Architectural Decisions:
    • Replaced specific on exception clauses with an open catch (_) block in render_object_selection.dart. On web compilation targets (dart2js and dart2wasm), host JavaScript runtimes can throw arbitrary values (including bare strings, JS objects, or null); Dart null safety excludes null from Object, making catch (_) the only clause that intercepts every possible thrown entity.
    • Latching _cachedUseHtmlRenderObject = true on any caught throwable prevents repeat probe execution and CPU thrashing during environmental rendering failures.
  • Non-Obvious Logic:
    • Checking if (_cachedUseHtmlRenderObject != null) prior to if (!kIsWeb && debugToImageSyncOverride == null) allows non-web test environments (such as the Dart VM) to hermetically simulate both probe success and probe failure via debugToImageSyncOverride without allocating native browser surfaces.
  • Primary Review Files:
    • packages/vector_graphics/lib/src/render_object_selection.dart: Core fallback catch and caching logic.
    • packages/vector_graphics/test/render_object_selection_test.dart: Hermetic unit test suite covering string, error, exception, null, and foreign object throws, plus caching and reset semantics.

Pre-Review Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

Footnotes

  1. Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. ↩ ↩2

@github-actions github-actions Bot added p: vector_graphics triage-engine Should be looked at in engine triage labels Nov 3, 2026
@harryterkelsen
harryterkelsen marked this pull request as ready for review November 3, 2026 23:37

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the vector_graphics package to version 1.2.7. It modifies useHtmlRenderObject() to catch all throwables during surface creation or toImageSync, ensuring a reliable fallback to the HTML render object. It also introduces a debugToImageSyncOverride test hook and a debugResetUseHtmlRenderObject() helper to facilitate testing, along with a comprehensive set of unit tests for these changes. There are no review comments, so I have no feedback to provide.

@harryterkelsen harryterkelsen added the CICD Run CI/CD label Nov 3, 2026
@gaaclarke

Copy link
Copy Markdown
Member

@walley892 friendly ping

@walley892 walley892 added the autosubmit Merge PR when tree becomes green via auto submit App label Nov 11, 2026
@auto-submit
auto-submit Bot merged commit 5a7871b into flutter:main Nov 11, 2026
12 checks passed
opensource-fork-sync Bot pushed a commit to cla7aye15I4nd/opensource-flutter__flutter that referenced this pull request Nov 11, 2026
…er#196381)

flutter/packages@08faf64...653628e

2026-11-11 [email protected] Roll Flutter from
fffd8c2 to b98afb5 (31 revisions) (flutter/packages#13623)
2026-11-11 [email protected] [material_ui] Document how to
programmatically clear DropdownMenu selection (flutter/packages#13266)
2026-11-11 [email protected] [pigeon] Fix basePath resolution when
paths share a string prefix with basePath (flutter/packages#13342)
2026-11-11 [email protected]
[cupertino_ui] Fix CupertinoSheetRoute throwing when a drag ends during
a pending relayout (flutter/packages#13316)
2026-11-11 [email protected] [shared_preferences] Updates Pigeon to
30.0.1 to support multi-engine registration and deregistration.
(flutter/packages#13617)
2026-11-11 [email protected]
[vector_graphics] Catch any throwable in useHtmlRenderObject() and cache
HTML fallback (flutter/packages#13545)
2026-11-11 [email protected] [cupertino_ui]
Include selectionHandleColor in NoDefaultCupertinoThemeData equality
(flutter/packages#13450)
2026-11-11 [email protected] [flutter_svg] Remove failed async loads
from Cache._pending (flutter/packages#13604)
2026-11-11 [email protected] [pigeon] Adds Native Interop FFI codec
serialization for NS types (flutter/packages#13616)
2026-11-10 [email protected] [pigeon] Support multi-engine Native
Interop registration and instance-aware unregistration
(flutter/packages#13576)
2026-11-10 [email protected] [image_picker_ios] Convert the
iOS example app and UI tests to Swift (flutter/packages#13570)
2026-11-10 [email protected]
[cupertino_ui] Localize CupertinoActionSheet semantics label
(flutter/packages#13377)
2026-11-10 [email protected] [camera_android]
Fix stopVideoRecording returning JPEG when takePicture runs during
recording (flutter/packages#13070)
2026-11-10 [email protected] [google_sign_in_android] Rename keep.xml
to google_sign_in_keep.xml (flutter/packages#13475)
2026-11-10 [email protected] [web_benchmarks] Fix benchmark stalling
when only repainting views that are dirty (flutter/packages#13089)
2026-11-10 [email protected] Roll Flutter from
d463821 to fffd8c2 (21 revisions) (flutter/packages#13614)

If this roll has caused a breakage, revert this CL and set the roller
to dry run mode using the controls here:
https://autoroll.skia.org/r/flutter-packages-flutter-autoroll
Please CC [email protected] on the revert to ensure that a
human
is aware of the problem.

To file a bug in Flutter:
https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

autosubmit Merge PR when tree becomes green via auto submit App CICD Run CI/CD p: vector_graphics triage-engine Should be looked at in engine triage

Projects

None yet

3 participants