Skip to content

fix(firebase_core_tvos): pin the platform interface to the 15-element Pigeon window - #22

Open
MAUstaoglu wants to merge 1 commit into
mainfrom
fix/core-pigeon-payload-window
Open

fix(firebase_core_tvos): pin the platform interface to the 15-element Pigeon window#22
MAUstaoglu wants to merge 1 commit into
mainfrom
fix/core-pigeon-payload-window

Conversation

@MAUstaoglu

Copy link
Copy Markdown
Member

Blocks the pub.dev release of the Firebase ports. firebase_core_tvos 0.0.1 is currently broken for anyone who resolves it fresh, and every package in the family sits on top of it.

The problem

firebase_core_platform_interface 8.1.0 removed the recaptchaSiteKey field from CoreFirebaseOptions. That shortens the Pigeon payload:

interface CoreFirebaseOptions payload
7.0.0, 7.0.1 14 elements — predates the field
7.1.0 15 elements
8.0.0 15 elements
8.1.0 14 elements — field removed

Our generated native side decodes all fifteen:

// tvos/Classes/messages.g.m:182
pigeonResult.recaptchaSiteKey = GetNullableObjectAtIndex(list, 14);

// :115 — a plain NSArray subscript, so out-of-range raises rather than returning nil
static id GetNullableObjectAtIndex(NSArray<id> *array, NSInteger key) {
  id result = array[key];
  return (result == [NSNull null]) ? nil : result;
}

fromList: is the Dart → native direction (codec type 129, reached from the FirebaseCoreHostApi.initializeApp handler), so the exposed call is Firebase.initializeApp(options: ...) — what every example in this repo uses, and what the READMEs show. The no-argument Firebase.initializeApp() reads its options from the plist natively and travels the other way, where Dart simply ignores the extra element, so that form survives.

Nothing constrained the interface, so this is what the README's own dependency block resolved to before this change:

$ flutter pub get
+ firebase_core 4.13.0
+ firebase_core_platform_interface 8.1.0

Why the constraint is on the interface and not on firebase_core

Bounding firebase_core cannot express the compatible window. I tried >=4.11.0 <4.13.0 first and it does not work — firebase_core 4.12.1 declares firebase_core_platform_interface: ^8.0.0, which still admits 8.1.0:

$ flutter pub get     # with firebase_core: ">=4.11.0 <4.13.0"
firebase_core=4.12.1  firebase_core_platform_interface=8.1.0   # still broken

The coupling is to the interface's generated protocol, not to firebase_core's version, so that is where the constraint belongs. >=7.1.0 <8.1.0 admits exactly 7.1.0 and 8.0.0 — the two releases on a 15-element payload — and lets firebase_core float as far as it can underneath.

Verified

Every Firebase example in the repo now resolves inside the window:

firebase_core_tvos         core=4.12.1  interface=8.0.0
firebase_auth_tvos         core=4.12.1  interface=8.0.0
cloud_firestore_tvos       core=4.12.1  interface=8.0.0
firebase_storage_tvos      core=4.12.1  interface=8.0.0
firebase_messaging_tvos    core=4.12.1  interface=8.0.0
firebase_analytics_tvos    core=4.11.0  interface=7.1.0
$ python3 .github/scripts/check_repo.py .
Checked 17 package(s) under packages/
  OK — README rows, versions, required files, overrides and tvOS plugin classes all consistent.

$ dart analyze lib test
No issues found!

$ flutter test
All tests passed!

$ flutter pub publish --dry-run
# clean once committed

Not verified on hardware — this is measured at the protocol level (payload arity on both sides, and the actual resolutions above), not observed as a crash on an Apple TV.

Release order

This needs to publish as 0.0.2 before the remaining Firebase ports go out. The dependents declare firebase_core_tvos: ^0.0.1, which in Dart admits 0.0.2, so no constraint bumps are needed anywhere else — they pick the fix up transitively, and the interface bound propagates into their resolutions too.

Follow-ups deliberately left out of this PR:

… Pigeon window

firebase_core_platform_interface 8.1.0 removed recaptchaSiteKey from
CoreFirebaseOptions, so _toList sends 14 elements where 7.1.0 and 8.0.0
send 15. The generated native side decodes index 14 via an unguarded
NSArray subscript, so Firebase.initializeApp(options: ...) read past the
end of the list. 7.0.x predates the field and is equally incompatible.

Nothing constrained the interface before, so a fresh resolve from the
README's own dependency block picked 8.1.0.
@MAUstaoglu
MAUstaoglu requested a review from DenisovAV August 17, 2026 08:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant