Repository navigation
[camera_web] Fix TypeError when reading the torch capability - #12647
Merged
auto-submit[bot] merged 2 commits intoSep 8, 2026
Merged
Conversation
Browsers do not report the `torch` capability in the shape the Image Capture specification describes. The specification declares `sequence<boolean> torch`, and `package:web` is generated from it, but both Chromium and WebKit declare a bare `boolean torch` in their IDL. `NonStandardFieldsOnMediaTrackCapabilities.torchNullable` mirrored the specification, so reading it on a camera that has a flash threw before the torch could ever be applied. It surfaced differently per compiler: DDC threw a `TypeError`, dart2js a `NoSuchMethodError`, and dart2wasm an `ArgumentError`. Both `setFlashMode` and `takePicture` reach it. Reads the capability as `JSAny?` and adds `canEnableTorch`, which accepts either shape and reports false for anything else, so a browser that reports something unexpected raises `torchModeNotSupported` rather than crashing. Reading a sequence now also answers with `any` rather than `first`, which was both wrong for `[false, true]` and threw a `StateError` on an empty sequence. Fixes flutter/flutter#191384
Contributor
There was a problem hiding this comment.
Code Review
This pull request updates the camera_web package to handle different browser implementations of the torch capability. In pkg_web_tweaks.dart, torchNullable is changed from JSArray<JSBoolean>? to JSAny? to accommodate both bare booleans and boolean sequences. A new canEnableTorch getter is added to parse these types, and integration tests are introduced to verify the capability parsing across various formats. No review comments were provided, so there is no feedback to address.
mdebbar
approved these changes
Sep 2, 2026
mdebbar
left a comment
Contributor
There was a problem hiding this comment.
Looks good to me, thanks for the fix!
flutter-zl
self-requested a review
September 8, 2026 20:57
flutter-zl
approved these changes
Sep 8, 2026
pull Bot
pushed a commit
to Mattlk13/flutter
that referenced
this pull request
Sep 9, 2026
…er#192485) flutter/packages@9af9c60...36e088a 2026-09-09 daniel.leon@cloudsufi.com [quick_actions] Adopt code-excerpts for README (flutter/packages#12643) 2026-09-08 65155920+0xharkirat@users.noreply.github.com [camera_web] Fix TypeError when reading the torch capability (flutter/packages#12647) 2026-09-08 gibbonsj97@gmail.com [google_maps_flutter_web] Avoid replacing advanced marker content on move (flutter/packages#11952) 2026-09-08 mit@google.com [material_ui][cupertino_ui] Change issue tracker label in pubspec.yaml (flutter/packages#12792) 2026-09-08 saurabhmirajkar000@gmail.com [material_ui] Fix FilledButton Material 3 default style docs (flutter/packages#12620) 2026-09-08 21270878+elliette@users.noreply.github.com [infra] Use a modified no-response workflow in flutter/packages (flutter/packages#12745) 2026-09-08 21270878+elliette@users.noreply.github.com [material_ui] Migrate M3 Banner template to use new gen_defaults (flutter/packages#12734) 2026-09-08 engine-flutter-autoroll@skia.org Roll Flutter from 63170e9 to b444e78 (13 revisions) (flutter/packages#12791) 2026-09-08 fluttergithubbot@gmail.com Sync release-go_router-18.0.1 to main (flutter/packages#12725) 2026-09-08 fluttergithubbot@gmail.com Sync release-material_ui-1.1.1 to main (flutter/packages#12726) 2026-09-08 stuartmorgan@google.com [tool] Adopt `platform` 3.2.0 (flutter/packages#12789) 2026-09-07 50643541+Mairramer@users.noreply.github.com [material_ui] Fix SliverGeometry maxPaintExtent assertion in CarouselView.weighted (flutter/packages#12563) 2026-09-05 engine-flutter-autoroll@skia.org Roll Flutter from 5a6cfa7 to 63170e9 (15 revisions) (flutter/packages#12767) 2026-09-04 engine-flutter-autoroll@skia.org Manual roll Flutter from 70797e1 to 5a6cfa7 (52 revisions) (flutter/packages#12760) 2026-09-04 brackenavaron@gmail.com [material_ui] port drawer tests over from flutter/widgets (flutter/packages#12711) 2026-09-04 tarrinneal@gmail.com add cooldown (flutter/packages#12708) 2026-09-04 joeldumasbg@gmail.com [in_app_purchase] Support StoreKit 2 introductory offer eligibility JWS (flutter/packages#12584) 2026-09-04 21270878+elliette@users.noreply.github.com [material_ui] Migrate M3 Badge template to use new gen_defaults (flutter/packages#12733) 2026-09-04 stuartmorgan@google.com [google_maps_flutter] Convert heatmap controller to Swift (flutter/packages#12713) 2026-09-04 97480502+b-luk@users.noreply.github.com [material_ui] Remove unused `maintainState` constructor parameter in `scaffold_test.dart` (flutter/packages#12754) 2026-09-04 a1rwulf@users.noreply.github.com [video_player_avfoundation] Route video over AirPlay (flutter/packages#12490) 2026-09-04 jerome.dellamaria@proton.me [google_fonts] Add google_fonts_lite file to allow tree-shaking of the other huge files (flutter/packages#11433) 2026-09-04 engine-flutter-autoroll@skia.org Roll Flutter from 0cbd1a4 to 70797e1 (27 revisions) (flutter/packages#12727) 2026-09-04 stuartmorgan@google.com Update Chrome for stable tests (flutter/packages#12747) 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 flutter-ecosystem@google.com 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
victorsanni
pushed a commit
to victorsanni/packages
that referenced
this pull request
Sep 9, 2026
…#12647) ## What broke `setFlashMode` and `takePicture` threw on any camera that has a flash. The Image Capture specification declares `sequence<boolean> torch` in `MediaTrackCapabilities`. `package:web` is generated from that specification, so `torchNullable` was typed `JSArray<JSBoolean>?`. No browser ships that shape. Chromium and WebKit both declare a bare `boolean torch`. Reading the property threw before the torch could be applied. The error depends on the compiler: | Compiler | Error | | --- | --- | | DDC | `TypeError: true: type 'bool' is not a subtype of type 'JSArray<Object?>?'` | | dart2js | `NoSuchMethodError: method not found: 'gq'` | | dart2wasm | `ArgumentError: Invalid argument(s)` | The same line held two more defects: - `.first` gave the wrong answer for `[false, true]`. A specification-shaped sequence lists the values the source accepts, so that means the torch can be turned on. - `.first` threw `StateError` on an empty sequence. ## The fix Read `torch` as `JSAny?` and add `canEnableTorch`, which accepts either shape and returns false for anything else. A sequence is answered with `any` instead of `first`, and is only trusted when every element is a boolean. Anything unrecognised raises `torchModeNotSupported` instead of crashing, and prints a debug-only warning so the shape can be reported. ## Test matrix | Browser reports | Before | After | | --- | --- | --- | | `true` | TypeError | torch on | | `false` | TypeError | torchModeNotSupported | | `[false, true]` | wrong answer | torch on | | `[true]` | torch on | torch on | | `[false]` | torchModeNotSupported | torchModeNotSupported | | `[]` | StateError | torchModeNotSupported | | key absent | torchModeNotSupported | torchModeNotSupported | | `'yes'` | TypeError | torchModeNotSupported + warning | | `['yes']` | TypeError | torchModeNotSupported + warning | Nine cases are covered by integration tests. Six of them fail without this change. ## Devices tested All nine shapes were run through the real plugin code on each of these. All passed. | Device | Browser | Result | | --- | --- | --- | | Moto G56 5G, Android 16 | Chrome 151 | 9 / 9 | | macOS 26.3 | Safari 26.3 | 9 / 9 | | iPhone 17 Pro simulator, iOS 26.1 | Safari | 9 / 9 | | macOS 26.3 | Chrome 151, dart2js and dart2wasm | 9 / 9 | On the Moto G56 the rear camera reports `torch: true` as a bare boolean, and the flash now turns on. The front camera does not report the key at all and raises `torchModeNotSupported` as expected. ## What was added - `canEnableTorch` on `NonStandardFieldsOnMediaTrackCapabilities`, which reads either shape. - A debug-only `debugPrint` warning for a shape that is neither, so an unknown browser can be reported rather than failing quietly. - Nine integration tests covering every shape, plus a check that a recognised shape never warns. - A CHANGELOG entry and a version bump to `0.3.5+6`. ## What was removed - The `JSArray<JSBoolean>?` type on `torchNullable`, which no browser matches. - The `?.toDart.first.toDart ?? false` chain in `_setTorchMode`. ## Issues fixed by this PR Fixes flutter/flutter#191384 ## Pre-Review Checklist 🤖 Generated with [Claude Code](https://claude.com/claude-code)
victorsanni
pushed a commit
to victorsanni/packages
that referenced
this pull request
Sep 9, 2026
…#12647) ## What broke `setFlashMode` and `takePicture` threw on any camera that has a flash. The Image Capture specification declares `sequence<boolean> torch` in `MediaTrackCapabilities`. `package:web` is generated from that specification, so `torchNullable` was typed `JSArray<JSBoolean>?`. No browser ships that shape. Chromium and WebKit both declare a bare `boolean torch`. Reading the property threw before the torch could be applied. The error depends on the compiler: | Compiler | Error | | --- | --- | | DDC | `TypeError: true: type 'bool' is not a subtype of type 'JSArray<Object?>?'` | | dart2js | `NoSuchMethodError: method not found: 'gq'` | | dart2wasm | `ArgumentError: Invalid argument(s)` | The same line held two more defects: - `.first` gave the wrong answer for `[false, true]`. A specification-shaped sequence lists the values the source accepts, so that means the torch can be turned on. - `.first` threw `StateError` on an empty sequence. ## The fix Read `torch` as `JSAny?` and add `canEnableTorch`, which accepts either shape and returns false for anything else. A sequence is answered with `any` instead of `first`, and is only trusted when every element is a boolean. Anything unrecognised raises `torchModeNotSupported` instead of crashing, and prints a debug-only warning so the shape can be reported. ## Test matrix | Browser reports | Before | After | | --- | --- | --- | | `true` | TypeError | torch on | | `false` | TypeError | torchModeNotSupported | | `[false, true]` | wrong answer | torch on | | `[true]` | torch on | torch on | | `[false]` | torchModeNotSupported | torchModeNotSupported | | `[]` | StateError | torchModeNotSupported | | key absent | torchModeNotSupported | torchModeNotSupported | | `'yes'` | TypeError | torchModeNotSupported + warning | | `['yes']` | TypeError | torchModeNotSupported + warning | Nine cases are covered by integration tests. Six of them fail without this change. ## Devices tested All nine shapes were run through the real plugin code on each of these. All passed. | Device | Browser | Result | | --- | --- | --- | | Moto G56 5G, Android 16 | Chrome 151 | 9 / 9 | | macOS 26.3 | Safari 26.3 | 9 / 9 | | iPhone 17 Pro simulator, iOS 26.1 | Safari | 9 / 9 | | macOS 26.3 | Chrome 151, dart2js and dart2wasm | 9 / 9 | On the Moto G56 the rear camera reports `torch: true` as a bare boolean, and the flash now turns on. The front camera does not report the key at all and raises `torchModeNotSupported` as expected. ## What was added - `canEnableTorch` on `NonStandardFieldsOnMediaTrackCapabilities`, which reads either shape. - A debug-only `debugPrint` warning for a shape that is neither, so an unknown browser can be reported rather than failing quietly. - Nine integration tests covering every shape, plus a check that a recognised shape never warns. - A CHANGELOG entry and a version bump to `0.3.5+6`. ## What was removed - The `JSArray<JSBoolean>?` type on `torchNullable`, which no browser matches. - The `?.toDart.first.toDart ?? false` chain in `_setTorchMode`. ## Issues fixed by this PR Fixes flutter/flutter#191384 ## Pre-Review Checklist 🤖 Generated with [Claude Code](https://claude.com/claude-code)
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.
What broke
setFlashModeandtakePicturethrew on any camera that has a flash.The Image Capture specification declares
sequence<boolean> torchinMediaTrackCapabilities.package:webis generated from that specification, sotorchNullablewas typedJSArray<JSBoolean>?.No browser ships that shape. Chromium and WebKit both declare a bare
boolean torch.Reading the property threw before the torch could be applied. The error depends on
the compiler:
TypeError: true: type 'bool' is not a subtype of type 'JSArray<Object?>?'NoSuchMethodError: method not found: 'gq'ArgumentError: Invalid argument(s)The same line held two more defects:
.firstgave the wrong answer for[false, true]. A specification-shaped sequencelists the values the source accepts, so that means the torch can be turned on.
.firstthrewStateErroron an empty sequence.The fix
Read
torchasJSAny?and addcanEnableTorch, which accepts either shape andreturns false for anything else.
A sequence is answered with
anyinstead offirst, and is only trusted when everyelement is a boolean. Anything unrecognised raises
torchModeNotSupportedinstead ofcrashing, and prints a debug-only warning so the shape can be reported.
Test matrix
truefalse[false, true][true][false][]'yes'['yes']Nine cases are covered by integration tests. Six of them fail without this change.
Devices tested
All nine shapes were run through the real plugin code on each of these. All passed.
On the Moto G56 the rear camera reports
torch: trueas a bare boolean, and the flashnow turns on. The front camera does not report the key at all and raises
torchModeNotSupportedas expected.What was added
canEnableTorchonNonStandardFieldsOnMediaTrackCapabilities, which reads either shape.debugPrintwarning for a shape that is neither, so an unknown browser canbe reported rather than failing quietly.
0.3.5+6.What was removed
JSArray<JSBoolean>?type ontorchNullable, which no browser matches.?.toDart.first.toDart ?? falsechain in_setTorchMode.Issues fixed by this PR
Fixes flutter/flutter#191384
Pre-Review Checklist
[shared_preferences]///).🤖 Generated with Claude Code