Release 1.4.2 — Flutter 3.44.7 + Platform.isTvOS in debug - #43
Merged
Conversation
Bump flutter.version to c9a6c484 (Flutter 3.44.2) and engine.version to v1.0.0-flutter3.44.2. Engine artifacts rebuilt against Dart d684a576. A Flutter-version-only bump keeps simulator/debug working but breaks AOT with 'gen_snapshot: Invalid SDK hash' (old gen_snapshot cannot load kernel compiled by the new Dart SDK), so the engine rebuild is required for device/release builds.
Platform.operatingSystem / isIOS / isTvOS carry @pragma("vm:platform-const"), which gen_snapshot const-folds in AOT from the build's --target-os. Stock Flutter passes --target-os ios for TargetPlatform.ios (which tvOS rides), so release baked in operatingSystem == "ios" and isTvOS == false for all app and plugin code — correct in JIT/debug, dead on device in release. Keep debug and release on the same runtime-resolution path: - TvosKernelSnapshot.build() mirrors upstream KernelSnapshot.build() but passes targetOS: null, so the platform-const getters are not folded and resolve at runtime to "tvos" (the engine's patched kHostOperatingSystemName). - TvosArtifacts overrides flutterPatchedSdkPath / platformKernelDill for AOT only to the patched flutter_patched_sdk in the host engine artifact, so the un-folded isIOS initializer is operatingSystem == "ios" || == "tvos" and the isTvOS getter exists. Debug keeps the stock SDK (runtime resolution via the device engine makes the compile SDK irrelevant there). Verified on a physical Apple TV in release: operatingSystem == "tvos", isIOS == true, isTvOS == true, defaultTargetPlatform == iOS. Plugin isolation is unaffected — discovery is keyed on the pubspec tvos: key, not Platform.isIOS. Adds unit tests asserting the AOT frontend_server command omits --target-os and that the artifact override applies for AOT but falls through to stock for debug. The example info screen now surfaces the platform-identity values.
At app startup the native FlutterTvRemotePlugin may not have registered its button-channel handler yet when init() pushes the initial config. The one-shot invocation then throws MissingPluginException and the handshake is lost — native never sets frameworkReadyForTouches and the touchpad appears dead even though everything compiled. Retry on a short interval until the call is acknowledged or a newer config supersedes it. Guarded by a generation counter so a superseded or reset push bails out, and never runs on iOS/Android (init() is isTvos-gated).
1.3.1 was never tagged, and the platform-identity fix landed on the same branch on top of the engine bump, so the release now carries a real CLI behaviour change. Drop the "no CLI behaviour change" note, add a Fixed section for the AOT Platform.operatingSystem/isIOS/isTvOS correction, note the bundled flutter_tvos 1.1.1, and move the date to the actual ship date.
Profile builds crashed at startup with `Type '_NetworkProfiling' not found in library 'dart.io'`. The patched-SDK override pointed both profile and release at the product host_release SDK, but the non-product profile engine looks up entry-point classes (e.g. dart:io _NetworkProfiling) that the product SDK doesn't retain through AOT tree-shaking. Map profile to the non-product host_debug_unopt SDK (which also carries the platform-identity patch), matching stock Flutter's flutter_patched_sdk (profile) vs flutter_patched_sdk_product (release) split. Release is unchanged. Verified on a physical Apple TV.
The device-debug engine now maps JIT pages RWX up front so on-device --debug + hot reload work again on tvOS 26 (which denies the RW<->RX mprotect flip). Ships in the v1.0.0-flutter3.44.2 engine artifacts; debug-only, AOT keeps W^X.
Guards that debug+simulator → tvos_debug_sim_arm64, debug+device → tvos_debug_arm64, profile → tvos_profile_arm64, release → tvos_release_arm64. A wrong mapping here is how a run mode silently picks the wrong engine.
… review I1/I2) Addresses review feedback on the configure-handshake retry: - I1: _pushConfigWithRetry now only swallows the expected MissingPluginException / PlatformException. Any other error (e.g. a _config.toMap() serialization bug) propagates instead of being retried 50x and dropped indistinguishably from the startup race. On budget exhaustion it reports via FlutterError.reportError instead of giving up silently, consistent with the rest of the class. - I2: rewrote the retry test with fakeAsync + virtual-time ticks so it no longer leans on a real-wall-clock window a starved CI runner could blow. The unregistered-native state is modelled by a mock handler that throws MissingPluginException (a null handler would fall through to the real platform dispatcher, which fakeAsync can't pump). Added a test that the retry budget exhausting reports an error.
Stock `flutter precache` with no platform flags downloads every enabled platform's artifacts (Android, iOS-engine, web, macOS). A tvOS embedder needs none of those. The command now drives the cache itself instead of delegating to `super.runCommand()`: it fetches the tvOS engine set plus the universal artifacts (fonts, patched SDK, host USB-deploy tools) and nothing else, while still honouring the stock per-platform flags (`--ios`, `--android`, `--all-platforms`, …) when passed explicitly. Also render the tvOS engine zips under a "tvOS Engine" header in the same nested tree style (` ├─ [1/6] …`) as the bundled Flutter SDK artifact.
`flutter-tvos create` with no output directory crashed with `Bad state: No element` because runCommand() read `rest.first` before validating. Call `validateOutputDirectoryArg()` up front so it prints the friendly usage message and exits with code 2, matching stock `flutter create`.
fix(cli): precache only tvOS + universal artifacts; create exits with usage
Refresh the pinned engine to Flutter 3.44.3 (e1fd963c, Dart d684a576). - bin/internal/flutter.version -> e1fd963c (Flutter 3.44.3) - bin/internal/engine.version -> v1.0.0-flutter3.44.3 - pubspec version -> 1.3.2 - Rebuilt all six engine artifact variants from the 3.44.3 source tree; all 17 tvOS patches apply cleanly and the artifact verification gate passes. Dart is unchanged, so AOT loads kernel without an SDK-hash mismatch. - Picks up the Flutter 3.44.3 flutter_tools fixes shipped in the SDK. Verified: dart analyze lib/ (0 errors), 262 tests pass, simulator-debug build succeeds, release AOT produces a valid App.framework.
- Root README "Current version" table -> flutter-tvos 1.3.2, Flutter SDK 3.44.3 (e1fd963c), engine artifacts v1.0.0-flutter3.44.3. - flutter_tvos package README: install snippet -> ^1.1.1 and add Siri Remote support to the feature list (it shows on pub.dev).
Docs-only release so the pub.dev page picks up the README changes (Siri Remote in the feature list, updated install snippet). No functional or API changes. - packages/flutter_tvos/pubspec.yaml -> 1.1.2 - packages/flutter_tvos CHANGELOG + README (install snippet ^1.1.2) - example pubspec.lock -> 1.1.2 - CLI CHANGELOG: note bundled plugin 1.1.2 Not published — publish to pub.dev after this merges to main.
Opening a plugin's tvos/Package.swift in Xcode generates .swiftpm/xcode/xcuserdata/ (per-user scheme state, e.g. xcschememanagement.plist) which is not source and must not be committed. - Add packages/flutter_tvos/tvos/.gitignore (.swiftpm/, xcuserdata/) — the bundled plugin's tvos/ had no .gitignore, so this junk was unignored. - Add the same rules to the porter's generated .gitignore (lib/plugin_porting/templates.dart), since the porter now emits a tvos/Package.swift and every ported plugin would otherwise hit this.
Upgrade to Flutter 3.44.3 (CLI 1.3.2, flutter_tvos 1.1.2)
# Conflicts: # CHANGELOG.md # bin/internal/engine.version # bin/internal/flutter.version # packages/flutter_tvos/CHANGELOG.md # packages/flutter_tvos/pubspec.yaml # pubspec.yaml
…; add tests Addresses self-review findings on the precache scoping logic: - Extract the non-tvOS artifact selection into a pure, @VisibleForTesting `selectRequiredArtifacts(...)` and cover it with unit tests (test/general/tvos_precache_test.dart): default = universal+informative only, explicit platform flags add their artifacts, --all-platforms, feature-gating, and the android umbrella/child flags. - Guard `argResults.wasParsed(name)` with `argParser.options.containsKey` so a future Flutter DevelopmentArtifact without a matching precache flag cannot crash the command. - Honor an individual `--android_gen_snapshot/_maven/_internal_build` flag on its own, not only via the `--android` umbrella. - Drop the misleading `cache.isUpToDate()` fast-path: it checks every registered artifact (including platforms we intentionally skip), so it was effectively always false. `updateAll` is already idempotent per-artifact. - Add a test for `flutter-tvos create` with no output directory exiting with usage (code 2) instead of crashing (test/general/tvos_create_test.dart), plus a test/src re-export shim for createTestCommandRunner.
Running TvosCreateCommand through createTestCommandRunner pulls the full FlutterCommand pipeline, which transitively touches `Pub` — the flutter_tools test harness rejects that with "Attempted to invoke pub during test" (passes locally, fails in CI). The create no-output-dir fix is a single stock `validateOutputDirectoryArg()` call and is unchanged; the substantive coverage (precache artifact selection) is fully tested in tvos_precache_test.dart.
# Conflicts: # CHANGELOG.md # README.md # bin/internal/engine.version # bin/internal/flutter.version # pubspec.yaml
All PRs now target dev; main only receives release merges. The PR template asks for a CHANGELOG [Unreleased] entry, test/analyze runs, hardware or simulator verification, and reminds contributors that the ObjC and Swift registrant/template variants must be updated together.
…unning (physical tvOS debug) (#37) * fix: skip plugin registration with a clear message when the engine is not running On a physical Apple TV the debug engine only starts with a debugger attached (see doc/architecture.md). Launched standalone, the engine never comes up and the generated registrant passes a nil registrar into the first Swift plugin, crashing with an unsymbolized SIGSEGV that blames that plugin. Probe the registry once with a synthetic key and, when it returns nil, log a clear message naming the cause and skip registration instead of crashing. * docs(changelog): note the standalone-debug-launch registration guard under [Unreleased] --------- Co-authored-by: Mehmet Ali Ustaoğlu <ali.ustaoglu@icloud.com>
….4.1) (#39) * chore: bump engine and SDK to Flutter 3.44.6 Repins the Flutter SDK to 3.44.6 (ee80f08b) and the tvOS engine artifacts to v1.0.0-flutter3.44.6, and releases this as 1.4.1. 3.44.6 is a three-commit hotfix over 3.44.5 (a Linux native-assets crash fix and an Android Gradle jniLibs staging fix). It carries no engine source changes and no DEPS movement, so dart_revision is unchanged and there is no SDK-hash break. The artifacts were rebuilt from the 3.44.6 tree anyway so the engine tag and the SDK pin stay in lockstep; all 17 tvOS patches applied unchanged. Upstream's build_system targets were untouched, so the four mirrored subclasses (TvosKernelSnapshot, TvosCopyFlutterBundle, TvosDartPluginRegistrantTarget, TvosAotElfRelease) needed no re-mirroring. The rebuild used tvOS SDK 26.5 (Xcode 26.6) and is origin-signed, passing verify_artifacts.sh on all six variants. Verified against the new artifacts: dart analyze lib/ clean (0 errors, 0 warnings), 295 tests pass, simulator debug and device release/AOT builds both succeed with all 10 FFI symbols exported and App.framework at minos 13.0 (ITMS-90208 clear). Folds the unreleased #37 plugin-registration fix into the 1.4.1 entry. * fix: repin engine to v1.0.1-flutter3.44.6 (tvOS simulator metallib fix) Fixes #38 — apps crashed on the first frame on tvOS simulators older than 26, with all ~60 Impeller render pipelines failing "Target OS is incompatible" followed by a raw_ptr FATAL. The simulator engine embedded Impeller metallibs compiled for the *iOS* simulator (air64-apple-ios13.0.0-simulator). Metal validates a library's target platform when creating a pipeline, so the mismatch failed every pipeline; tvOS 26 tolerates it, which is why it only reproduced on older runtimes. The engine now compiles simulator metallibs against the AppleTVSimulator SDK (air64-apple-tvos13.0.0-simulator). Device builds were never affected. Engine fix in fluttertv/engine#6; artifacts republished under a new tag because the CLI caches by the engine.version string, so replacing assets on the existing tag would not refresh anyone who already precached. Verified on a tvOS 17.5 simulator with the flutter_tvos example: 60 errors and a FATAL before, 0 and 0 after, app launches and renders with hot reload and DevTools. tvOS 26.5 re-checked for regression. 297 tests pass, analyze clean.
) * Bump to Flutter 3.44.7 (1.4.2) Flutter 3.44.7 contains nothing that reaches the tvOS engine, so the engine artifacts are republished under the new name rather than rebuilt: v1.0.1-flutter3.44.7 is byte-identical to v1.0.1-flutter3.44.6. What is actually in the 3.44.6..3.44.7 range: one functional change, Android-side (FlutterRenderer.java, texture SyncFence lifetime). DEPS is byte-identical (same SHA1), the Dart submodule is unchanged, and darwin/, ios/ and impeller/ are untouched. The remaining four commits are CI config and changelog text. An unchanged Dart submodule is what makes this safe — the SDK hash our AOT artifacts embed does not move, so gen_snapshot and the patched flutter_patched_sdk stay compatible. Verified rather than assumed, using the artifacts as published and fetched fresh through precache with the local artifacts/ cache moved aside to force the download path: AOT/profile, physical Apple TV 4K (tvOS 26.5) operatingSystem=tvos isIOS=true isTvOS=true defaultTargetPlatform=TargetPlatform.iOS JIT/debug, tvOS 17.5 simulator runs clean, zero "Target OS is incompatible" verify_artifacts.sh passed, incl. designated-requirement signing CLI suite 297 passed; analyze reports no errors/warnings The 17.5 run matters because tvOS 26 tolerates a wrong metallib triple and older runtimes do not — it confirms the issue #38 fix still holds. Also recorded a pre-existing limitation found while probing: Platform.isTvOS compiles only in profile/release. Debug compiles against the stock Flutter SDK, which has no such getter, so an app using it fails to build in debug with "Member not found: 'isTvOS'". Reproduced identically on 1.4.1, so it is not introduced here. Platform.operatingSystem == 'tvos' works in every mode. * Make Platform.isTvOS compile in debug builds The README tells apps to distinguish Apple TV with Platform.isTvOS, but that only ever worked in profile/release. A debug build failed with `Member not found: 'isTvOS'`, which reproduces identically on 1.4.1, so this has been broken since the getter was introduced. TvosArtifacts pointed the patched flutter_patched_sdk override at precompiled modes only, reasoning that debug resolves platform identity at runtime via the device engine so the compile SDK is irrelevant. That reasoning holds for the *values*: in JIT, dart:io comes from the engine's own patched core libraries, which is why operatingSystem and isIOS were already correct in debug. What it misses is that isTvOS is a member the stock SDK does not declare at all, and the frontend server type-checks against the compile SDK before any of that runtime resolution happens. So debug now uses the same non-product patched SDK as profile. The host_debug_unopt artifact already shipped it — verify_artifacts.sh has been asserting the isTvOS patch is present in it all along; nothing was wiring it up. Verified, since the old comment's worry was disturbing the proven debug path: debug compile, Platform.isTvOS builds (was: Member not found) debug run, tvOS 17.5 simulator isTvOS=true, isIOS=true, operatingSystem=tvos, isAndroid/isMacOS unaffected AOT/profile, physical Apple TV 4K unchanged hot reload Reloaded 1 of 755 libraries, 190ms CLI suite 297 pass; analyze clean The two tests asserting debug fell through to stock resolution encoded the old decision and failed, which is what they were for; they now assert the patched SDK, plus a case for a null mode resolving to the non-product SDK rather than silently picking the product one.
Squash-merging the release PR onto main leaves main with a commit dev never sees, so the two diverge and the next dev->main PR conflicts on every version-carrying file. This absorbs that commit (a9ea725, the 1.4.1 release) back into dev so the 1.4.2 release PR is clean. Conflicts were CHANGELOG.md, README.md, pubspec.yaml, engine.version and flutter.version — all resolved in favour of dev, which carries the newer 3.44.7 / 1.4.2 values. Checked what taking dev's side discards: only the superseded 1.4.1 version strings. CHANGELOG needed no reconciling, dev's copy is already a superset containing both the 1.4.1 and 1.4.2 entries.
Merge main into dev (unblock the 1.4.2 release PR)
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.
Release PR for 1.4.2. Two changes.
Important
Merge this with "Create a merge commit", not squash. Squashing is what makes the next release PR conflict on every version file — it creates a commit
maincan't relate back todev's history, so the merge base slides back. Verified with a two-cycle simulation: squash → conflict on the following release, merge commit → clean. That's what #42 just had to clean up.1. Flutter 3.44.7 — no engine rebuild
v1.0.1-flutter3.44.7is byte-identical tov1.0.1-flutter3.44.6, republished under the new name. Nothing in 3.44.7 reaches the tvOS engine:FlutterRenderer.java)DEPSdarwin/·ios/·impeller/The unchanged Dart submodule is what makes this safe — the SDK hash our AOT artifacts embed doesn't move, so
gen_snapshotand the patchedflutter_patched_sdkstay kernel-compatible.2.
Platform.isTvOSnow compiles in debugThe README tells apps to use it, but it only ever worked in profile/release — debug failed with
Member not found: 'isTvOS'. Reproduced identically on 1.4.1, so it predates this release. Debug now compiles against the same patched SDK as profile, whichhost_debug_unoptalready shipped.Verified
Artifacts were fetched fresh through
precachewith the localartifacts/cache moved aside, so the download path users actually take is what got tested.After merging
v3.44.7-tvos.1.4.2+ GitHub release