From a78dc99f1dfaec2f0705d0f596eeb194579012a0 Mon Sep 17 00:00:00 2001 From: Jude Kwashie Date: Thu, 15 Oct 2026 16:38:38 +0000 Subject: [PATCH] fix(core,web): honour flutterfire_ignore_scripts under dart2wasm JS arrays are not Dart Iterables on dart2wasm, so the ignore list was always empty and skipped service scripts still loaded. Read the window value as a JSArray on both compilers. --- .../lib/src/firebase_core_web.dart | 21 ++++++---- ...firebase_core_web_ignore_scripts_test.dart | 41 +++++++++++++++++++ 2 files changed, 53 insertions(+), 9 deletions(-) create mode 100644 packages/firebase_core/firebase_core_web/test/firebase_core_web_ignore_scripts_test.dart diff --git a/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart b/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart index ea15ec3cc17a..54b94668c52d 100644 --- a/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart +++ b/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart @@ -117,16 +117,15 @@ class FirebaseCoreWeb extends FirebasePlatform { /// You must ensure the Firebase script is injected before using the service. List get _ignoredServiceScripts { try { - JSObject? ignored = + final ignored = globalContext.getProperty('flutterfire_ignore_scripts'.toJS); - - // Cannot be done with Dart 3.2 constraints - // ignore: invalid_runtime_check_with_js_interop_types - if (ignored is Iterable) { - // ignore: invalid_runtime_check_with_js_interop_types - return (ignored! as Iterable) - .map((e) => e.toString()) - .toList(growable: false); + if (ignored != null && ignored.isA()) { + return (ignored as JSArray).toDart.map((entry) { + if (entry != null && entry.isA()) { + return (entry as JSString).toDart; + } + return entry?.toString() ?? 'null'; + }).toList(growable: false); } } catch (e) { // Noop @@ -135,6 +134,10 @@ class FirebaseCoreWeb extends FirebasePlatform { return []; } + /// Services listed on `window.flutterfire_ignore_scripts`. + @visibleForTesting + List get ignoredServiceScripts => _ignoredServiceScripts; + final String _defaultTrustedPolicyName = 'flutterfire-'; /// Injects a `script` with a `src` dynamically into the head of the current diff --git a/packages/firebase_core/firebase_core_web/test/firebase_core_web_ignore_scripts_test.dart b/packages/firebase_core/firebase_core_web/test/firebase_core_web_ignore_scripts_test.dart new file mode 100644 index 000000000000..d680a32fe3e6 --- /dev/null +++ b/packages/firebase_core/firebase_core_web/test/firebase_core_web_ignore_scripts_test.dart @@ -0,0 +1,41 @@ +// Copyright 2026 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +@TestOn('browser') +library; + +import 'dart:js_interop'; +import 'dart:js_interop_unsafe'; + +import 'package:firebase_core_web/firebase_core_web.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + tearDown(() { + globalContext.delete('flutterfire_ignore_scripts'.toJS); + }); + + test('reads service names from a JS array on window', () { + // Matches `window.flutterfire_ignore_scripts = ['analytics'];` in index.html. + globalContext.callMethod( + 'eval'.toJS, + "window.flutterfire_ignore_scripts = ['analytics', 'firestore']".toJS, + ); + + expect( + FirebaseCoreWeb().ignoredServiceScripts, + ['analytics', 'firestore'], + ); + }); + + test('returns an empty list when the window property is missing', () { + expect(FirebaseCoreWeb().ignoredServiceScripts, isEmpty); + }); + + test('returns an empty list when the window property is not an array', () { + globalContext['flutterfire_ignore_scripts'] = 'analytics'.toJS; + + expect(FirebaseCoreWeb().ignoredServiceScripts, isEmpty); + }); +}