## 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 https://github.com/flutter/flutter/issues/191384
## Pre-Review Checklist
🤖 Generated with [Claude Code](https://claude.com/claude-code)