Migrate to Dart 3.3 and package:web (wasm-ready)#401
Merged
Conversation
Bumps the wiredash environment to Dart >=3.3.0 / Flutter >=3.19.0, unlocking modern web interop (and WebAssembly compilation). - Replace dart:html, dart:js, and dart:js_util with package:web and dart:js_interop in the web lifecycle backport, device info, and the renderer detection helper. - Switch conditional imports from `dart.library.html` to `dart.library.js_interop`, which is the wasm-compatible signal. - Clean up analyzer fallout from the SDK bump: parameter assignments in the backdrop animation builder, unnecessary http_parser imports, unnecessary library names, unnecessary breaks, unnecessary non-null assertions, and the CorePalette deprecation gets an ignore until CorePalettes is available across supported channels. - Drop the Flutter 3.0.0 example and CI jobs; the new min-version job targets Flutter 3.19.0.
Flutter 3.19's `flutter pub get` checks the Android embedding by looking at `build.gradle` (Groovy) and treats projects that only have `build.gradle.kts` as embedding v1 — which then fails plugins like `device_info_plus`. The fix landed in 3.24, so bump the min-version container there and reformat with the CI Dart version. The SDK itself still works on Dart 3.3.
The previous bump to Flutter 3.24 in the min-version job didn't match the declared `flutter: >=3.19.0` constraint. Going back to 3.19 in CI required a sample project that 3.19 can actually resolve — the older `old_flutter_3_0` sample used Flutter 3.0 era pubspec/Gradle layout, and our other examples use Kotlin Gradle (build.gradle.kts) which 3.19's `flutter pub get` mis-detects as embedding v1. - Add `examples/old_flutter_3_19_0`, generated by `flutter create` on Flutter 3.19.0 and wired up to wiredash via a local path dependency. - Drop the obsolete `examples/old_flutter_3_0` leftovers. - Point `pr-min` and the nightly `minVersion` job at `cirruslabs/flutter:3.19.0` and the new example. - Filter the new sample out of `wiresdk recreate-examples` since it intentionally sticks to the old Flutter 3.19 layout. - Restore the `http_parser` import in `wiredash_api.dart` with an `unnecessary_import` ignore: `MediaType` is re-exported by `package:http` only on Flutter >=3.22, so we still need the direct dependency for the 3.19 build, and re-export `MediaType` so downstream call sites keep compiling.
`./wiresdk deps` pulls every example package, but several rely on Dart 3.4+ APIs or Kotlin Gradle layouts that Flutter 3.19 can't resolve (notably `examples/wasm` which pins sdk ^3.11.5). Replace the catch-all with explicit `flutter pub get` calls in just the wiredash package and the 3.19 sample, then run `flutter test` and `flutter build web` against those two directly. Also pin the 3.19 sample's `flutter` constraint to 3.19.x and trim boilerplate from its pubspec.yaml. Reformat the two sample `lib/main.dart` files so `./wiresdk format --verify` is happy.
./wiresdk test/flutter wrap the system Flutter SDK and add nicer package iteration, so use them instead of bare flutter commands. The ./wiresdk deps step is still skipped here because it would pull every example, and several of them require Dart 3.4+ or newer Flutter tooling.
Renaming to 'transformed' was an over-correction for the new parameter_assignments warning. Keep the more readable 'app' name and silence the warning with a scoped ignore.
The non-null helper guarded against Flutter 2.11's nullable WidgetsBinding.instance. Min Flutter is now 3.19, so use WidgetsBinding.instance directly.
AppLifecycleState.hidden was added in Flutter 3.13 and our floor is now 3.19, so call sites can read it directly and the helper goes away. Also drop the leftover comment about not being able to use AppLifecycleListener — same Flutter 3.13 cutoff.
MediaQuery.fromView landed in Flutter 3.7.0-32.0.pre. Min Flutter is 3.19, so the deprecated MediaQuery.fromWindow path can go.
…View SingletonFlutterWindow / WindowPadding have been deprecated since Flutter 3.7.0-32.0.pre / 3.8.0-14.0.pre and we're now at Flutter 3.19, so swap FlutterInfoCollector and WiredashWindowPadding to FlutterView and ViewPadding. Services pass WidgetsBinding.instance .platformDispatcher.views.first.
Picasso reads physicalSize from the implicit FlutterView now, and the device_info dartdoc links point to the correct api.flutter.dev pages (FlutterView for view-scoped values, PlatformDispatcher for locale/brightness/textScaleFactor).
Wiredash.trackEvent runs on background isolates (e.g. via compute()
+ BackgroundIsolateBinaryMessenger). The earlier migration to
FlutterView passed the implicit view as a non-null argument, but
on a worker isolate PlatformDispatcher.implicitView trips an
assertion ('The implicit view ID is 0, but the implicit view does
not exist') and views.first throws because views is empty.
- Make FlutterInfoCollector accept a nullable FlutterView and fall
back to PlatformDispatcher defaults (locale, brightness,
textScaleFactor) and zero-padding/size when no view exists.
- Resolve the view in services.dart via
PlatformDispatcher.instance.views.firstOrNull-style guarding so
isolates pass null instead of triggering the assertion.
- Apply the same guard to PicassoController._sketcherCanvasSize.
Reproduced locally with
flutter test -d macos examples/theming/integration_test
which now passes again.
The earlier isolate-safety fix returned zeros (Size.zero, 1.0, zero-paddings) when there was no FlutterView, which silently synthesized misleading data. Mark all view-only fields nullable so absence is visible: - FlutterInfo: viewPadding, physicalSize, pixelRatio, viewInsets, gestureInsets - AllMetaData: windowInsets, windowPadding, windowPixelRatio, windowSize, platformGestureInsets Dispatcher-derived fields (platformLocale, platformSupportedLocales, platformBrightness, textScaleFactor) stay non-null because PlatformDispatcher.instance is available on any isolate. JSON serialization now skips the nullable fields when they are null, the same way other optional metadata is handled.
The macOS-latest runners frequently fail to foreground the
integration test app ('Failed to foreground app; open returned 1')
and the job then hangs until the default 6h timeout. Add a
15-minute job-level timeout and an 8-minute step-level timeout so
a known-bad run fails fast instead of clogging the runner pool.
macOS-latest runners can't foreground the test app reliably and the job hangs. Linux + Xvfb gives the integration test a virtual display, so flutter test -d linux integration_test can launch the app without needing a real GUI session.
2fb6888 to
b47a042
Compare
Look up the view via PlatformDispatcher.views.firstOrNull at capture time instead of carrying it through the constructor. Promote the shared body to a top-level captureBaseFlutterInfo() and replace the three view != null ternaries with a file-private ViewPadding extension that pairs with ?. short-circuiting.
Replace deprecated spot APIs: - spotSingleText → spotText - spotTexts → spotText (not spot<Text>().whereText()) - spotSingle<X>() → spot<X>() - spotSingle<X>(children:) → spot<X>(children:) - SingleWidgetSelector/Snapshot → WidgetSelector/Snapshot - hasProp(selector:) → hasWidgetProp(prop:) - Custom _tap → act.tap - waitUntil(isNot(screenshotDrawing)) was a pre-existing bug — should wait for drawing, not not-drawing - 'first trackEvent() is fast' relaxed to <=100ms since act.tap now pumps a frame
The v3 serializer now omits platformGestureInsets, windowInsets, windowPadding, windowPixelRatio and windowSize when the metadata was captured without a FlutterView (background isolate). The parser still cast every one of them as present and non-null, so any persisted item in that state failed to deserialize and got dropped on the next retrieval. Read them as optional and skip windowSize when missing. Add two tests: - parse v3 JSON with all FlutterView-derived fields omitted - round-trip a PendingFeedbackItem whose metadata has all view fields null, and assert the serializer drops the keys rather than writing nulls
^3.11.5 was both unusual (^ on an SDK constraint, inconsistent with the rest of the repo) and missing a Flutter floor. Use the standard >= / < pair and pin Flutter to >=3.22.0, when --wasm became stable.
Removing widget_binding_support.dart left an empty line where the import used to sit. dart format tolerates it but the original files had no blank between flutter and wiredash imports — restore that.
spot's loadAppFonts() reads wiredash's pubspec and registers Inter / Wirecons under their bare family names. But wiredash's TextStyles and IconDatas set package: 'wiredash', which Flutter resolves to packages/wiredash/Inter / packages/wiredash/Wirecons at lookup time. Without the prefixed registration the engine falls back to Ahem and all Wiredash text + icons render as empty boxes in test screenshots. Re-register both families under the package-prefixed names right after loadAppFonts(). Remove once spot bridges this for packages testing their own fonts (passsy/spot#141).
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.
Wiredash now requires Dart 3.3 / Flutter 3.19, drops every
dart:html/dart:js/dart:js_utilimport, and compiles to WebAssembly.Why
CI on
stablebroke after the latest Flutter docker image moved to Dart 3.11 — the analyzer rejectsdart:js_util,parameter_assignmentsis now strict, andhttp_parser/library/breakinfos became errors. Plastering on more// ignore:lines wouldn't carry us forward, so this jumps to Dart 3.3 and the modern JS-interop stack instead.Web migration
dart:htmltypes +document/windowpackage:web(web.document,web.window,web.Event,web.MutationObserver, …)dart:js_util.callMethod(document, 'hasFocus', [])web.document.hasFocus()dart:js'js.context['flutterCanvasKit']@JS('flutterCanvasKit') external JSAny? get _flutterCanvasKitif (dart.library.html)conditional importsif (dart.library.js_interop)(wasm-compatible)flutter build web --wasmnow works end-to-end. A newexamples/wasmsample exercises that build in nightly CI.SDK floor
sdk: '>=3.3.0 <4.0.0',flutter: '>=3.19.0'examples/old_flutter_3_19_0(created withflutter createon Flutter 3.19.0) drives thepr-minand nightlyminVersionjobs againstcirruslabs/flutter:3.19.0, matching the declared floor exactly.examples/old_flutter_3_0and its CI jobs are gone.Analyzer fallout
Cleaned up under the bumped lint set:
parameter_assignments— kept theappparameter name inWiredashBackdrop._buildAppPositioningAnimationwith a scoped// ignore:; rewroteWiredashThemeData.fromColorto use a local.unnecessary_import—http_parserstays inwiredash_api.dart(Flutter 3.19'spackage:httpdoesn't re-exportMediaTypeyet) with an ignore +export 'package:http_parser/http_parser.dart' show MediaTypeso callers stay decoupled.librarydirectives, unusedbreak;s, redundant!s.CorePalettestays with a focused// ignore: deprecated_member_use—CorePalettesisn't available across all of our supported channels yet.Fixes #402