From 3f236bcbb53fa371bd7340dc79dd09a372b55237 Mon Sep 17 00:00:00 2001 From: MichaelVerdon Date: Mon, 27 Oct 2025 12:36:05 +0000 Subject: [PATCH 1/5] fix(firestore, web): More explicit interop types --- .../lib/src/interop/firestore.dart | 4 +- .../lib/src/interop/firestore_interop.dart | 141 +++--------------- 2 files changed, 24 insertions(+), 121 deletions(-) diff --git a/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore.dart b/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore.dart index 8b55b4e68ae6..909a2df910ee 100644 --- a/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore.dart +++ b/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore.dart @@ -719,8 +719,8 @@ class CollectionReference return _expando[jsObject] ??= CollectionReference._fromJsObject(jsObject); } - factory CollectionReference() => CollectionReference._fromJsObject( - firestore_interop.CollectionReferenceJsImpl()); + factory CollectionReference(firestore_interop.CollectionReferenceJsImpl jsObject) => + CollectionReference._fromJsObject(jsObject); CollectionReference._fromJsObject( firestore_interop.CollectionReferenceJsImpl jsObject) diff --git a/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart b/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart index 56fcced541fb..d5eaafd8b0ee 100644 --- a/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart +++ b/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart @@ -344,11 +344,7 @@ extension FirestoreJsImplExtension on FirestoreJsImpl { external JSString get type; } -@JS('WriteBatch') -@staticInterop -abstract class WriteBatchJsImpl {} - -extension WriteBatchJsImplExtension on WriteBatchJsImpl { +extension type WriteBatchJsImpl._(JSObject _) implements JSObject { external JSPromise commit(); external WriteBatchJsImpl delete(DocumentReferenceJsImpl documentRef); @@ -363,13 +359,7 @@ extension WriteBatchJsImplExtension on WriteBatchJsImpl { ); } -@JS('CollectionReference') -@staticInterop -class CollectionReferenceJsImpl extends QueryJsImpl { - external factory CollectionReferenceJsImpl(); -} - -extension CollectionReferenceJsImplExtension on CollectionReferenceJsImpl { +extension type CollectionReferenceJsImpl._(JSObject _) implements QueryJsImpl { external JSString get id; external DocumentReferenceJsImpl get parent; external JSString get path; @@ -430,11 +420,7 @@ extension GeoPointJsImplExtension on GeoPointJsImpl { @staticInterop external VectorValueJsImpl get VectorValueConstructor; -@JS('VectorValue') -@staticInterop -class VectorValueJsImpl {} - -extension VectorValueJsImplExtension on VectorValueJsImpl { +extension type VectorValueJsImpl._(JSObject _) implements JSObject { external JSArray toArray(); } @@ -464,12 +450,7 @@ extension BytesJsImplExtension on BytesJsImpl { external JSBoolean isEqual(JSObject other); } -@anonymous -@JS() -@staticInterop -abstract class DocumentChangeJsImpl {} - -extension DocumentChangeJsImplExtension on DocumentChangeJsImpl { +extension type DocumentChangeJsImpl._(JSObject _) implements JSObject { external JSString /*'added'|'removed'|'modified'*/ get type; external set type(JSString /*'added'|'removed'|'modified'*/ v); @@ -491,11 +472,8 @@ extension DocumentChangeJsImplExtension on DocumentChangeJsImpl { @staticInterop external DocumentReferenceJsImpl get DocumentReferenceJsConstructor; -@JS('DocumentReference') -@staticInterop -abstract class DocumentReferenceJsImpl {} -extension DocumentReferenceJsImplExtension on DocumentReferenceJsImpl { +extension type DocumentReferenceJsImpl._(JSObject _) implements JSObject { external FirestoreJsImpl get firestore; external JSString get id; external CollectionReferenceJsImpl get parent; @@ -511,11 +489,7 @@ extension QueryConstraintJsImplExtension on QueryConstraintJsImpl { external JSString get type; } -@JS('LoadBundleTask') -@staticInterop -abstract class LoadBundleTaskJsImpl {} - -extension LoadBundleTaskJsImplExtension on LoadBundleTaskJsImpl { +extension type LoadBundleTaskJsImpl._(JSObject _) implements JSObject { external void onProgress( JSFunction? next, ); @@ -526,13 +500,7 @@ extension LoadBundleTaskJsImplExtension on LoadBundleTaskJsImpl { ]); } -@JS() -@staticInterop -@anonymous -abstract class LoadBundleTaskProgressJsImpl {} - -extension LoadBundleTaskProgressJsImplExtension - on LoadBundleTaskProgressJsImpl { +extension type LoadBundleTaskProgressJsImpl._(JSObject _) implements JSObject { // int or String? external JSAny get bytesLoaded; @@ -546,11 +514,7 @@ extension LoadBundleTaskProgressJsImplExtension external JSNumber get totalDocuments; } -@JS('DocumentSnapshot') -@staticInterop -abstract class DocumentSnapshotJsImpl {} - -extension DocumentSnapshotJsImplExtension on DocumentSnapshotJsImpl { +extension type DocumentSnapshotJsImpl._(JSObject _) implements JSObject { external JSString get id; external SnapshotMetadata get metadata; external DocumentReferenceJsImpl get ref; @@ -564,12 +528,7 @@ extension DocumentSnapshotJsImplExtension on DocumentSnapshotJsImpl { /// [set()] or [update()]. /// /// See: . -@JS() -@staticInterop -@anonymous -abstract class FieldValue {} - -extension FieldValueExtension on FieldValue { +extension type FieldValue._(JSObject _) implements JSObject { /// Returns `true` if this [FieldValue] is equal to the provided [other]. external JSBoolean isEqual(FieldValue other); } @@ -579,20 +538,12 @@ extension FieldValueExtension on FieldValue { @staticInterop external JSObject get fieldValues; -@JS('Query') -@staticInterop -abstract class QueryJsImpl {} - -extension QueryJsImplExtension on QueryJsImpl { +extension type QueryJsImpl._(JSObject _) implements JSObject { external FirestoreJsImpl get firestore; external JSString get type; } -@JS('QuerySnapshot') -@staticInterop -abstract class QuerySnapshotJsImpl {} - -extension QuerySnapshotJsImplExtension on QuerySnapshotJsImpl { +extension type QuerySnapshotJsImpl._(JSObject _) implements JSObject { external JSArray get docs; external JSBoolean get empty; external SnapshotMetadata get metadata; @@ -607,11 +558,7 @@ extension QuerySnapshotJsImplExtension on QuerySnapshotJsImpl { ]); } -@JS('Transaction') -@staticInterop -abstract class TransactionJsImpl {} - -extension TransactionJsImplExtension on TransactionJsImpl { +extension type TransactionJsImpl._(JSObject _) implements JSObject { external TransactionJsImpl delete(DocumentReferenceJsImpl documentRef); external JSPromise get(DocumentReferenceJsImpl documentRef); @@ -796,53 +743,28 @@ abstract class FirestoreLocalCache {} /// /// To use, create an instance using the factory function , then set the instance to FirestoreSettings.cache /// and call initializeFirestore using the settings object. -@anonymous -@JS() -@staticInterop -abstract class MemoryLocalCache extends FirestoreLocalCache {} - -extension MemoryLocalCacheExtension on MemoryLocalCache { +extension type MemoryLocalCache._(JSObject _) implements JSObject { external JSString get kind; } /// A tab manager supporting only one tab, no synchronization will be performed across tabs. -@anonymous -@JS() -@staticInterop -abstract class PersistentSingleTabManager {} - -extension PersistentSingleTabManagerExtension on PersistentSingleTabManager { +extension type PersistentSingleTabManager._(JSObject _) implements JSObject { external JSString get kind; } /// A tab manager supporting multiple tabs. SDK will synchronize queries and mutations done across all tabs using the SDK. -@anonymous -@JS() -@staticInterop -abstract class PersistentMultipleTabManager {} - -extension PersistentMultipleTabManagerExtension - on PersistentMultipleTabManager { +extension type PersistentMultipleTabManager._(JSObject _) implements JSObject { external JSString get kind; } /// A garbage collector deletes documents whenever they are not part of any active queries, and have no local mutations attached to them. -@anonymous -@JS() -@staticInterop -abstract class MemoryEagerGarbageCollector {} - -extension MemoryEagerGarbageCollectorExtension on MemoryEagerGarbageCollector { +/// +extension type MemoryEagerGarbageCollector._(JSObject _) implements JSObject { external JSString get kind; } /// A garbage collector deletes Least-Recently-Used documents in multiple batches. -@anonymous -@JS() -@staticInterop -abstract class MemoryLruGarbageCollector {} - -extension MemoryLruGarbageCollectorExtension on MemoryLruGarbageCollector { +extension type MemoryLruGarbageCollector._(JSObject _) implements JSObject { external JSString get kind; } @@ -850,12 +772,7 @@ extension MemoryLruGarbageCollectorExtension on MemoryLruGarbageCollector { /// /// To use, create an instance using the factory function , then set the instance to FirestoreSettings.cache /// and call initializeFirestore using the settings object. -@anonymous -@JS() -@staticInterop -abstract class PersistentLocalCache extends FirestoreLocalCache {} - -extension PersistentLocalCacheExtension on PersistentLocalCache { +extension type PersistentLocalCache._(JSObject _) implements JSObject { external JSString get kind; } @@ -912,12 +829,7 @@ extension PersistentCacheSettingsExtension on PersistentCacheSettings { /// An settings object to configure an PersistentLocalCache instance. /// /// See: . -@JS() -@staticInterop -abstract class PersistentSingleTabManagerSettings {} - -extension PersistentSingleTabManagerSettingsExtension - on PersistentSingleTabManagerSettings { +extension type PersistentSingleTabManagerSettings._(JSObject _) implements JSObject { /// Whether to force-enable persistent (IndexedDB) cache for the client. /// This cannot be used with multi-tab synchronization and is primarily /// intended for use with Web Workers. @@ -931,11 +843,7 @@ extension PersistentSingleTabManagerSettingsExtension /// Metadata about a snapshot, describing the state of the snapshot. /// /// See: . -@JS() -@staticInterop -abstract class SnapshotMetadata {} - -extension SnapshotMetadataExtension on SnapshotMetadata { +extension type SnapshotMetadata._(JSObject _) implements JSObject { /// [:true:] if the snapshot includes local writes (set() or update() calls) /// that haven't been committed to the backend yet. If your listener has opted /// into metadata updates via onDocumentMetadataSnapshot, @@ -1091,12 +999,7 @@ external JSPromise getAggregateFromServer( JSObject specs, ); -@JS('AggregateQuerySnapshot') -@staticInterop -abstract class AggregateQuerySnapshotJsImpl {} - -extension AggregateQuerySnapshotJsImplExtension - on AggregateQuerySnapshotJsImpl { +extension type AggregateQuerySnapshotJsImpl._(JSObject _) implements JSObject { external JSObject data(); } From 7f4dfd5f860703d6db2246f630a68ef062f43b8e Mon Sep 17 00:00:00 2001 From: MichaelVerdon Date: Mon, 27 Oct 2025 12:42:17 +0000 Subject: [PATCH 2/5] fix: JSPromise types --- .../lib/src/interop/firestore_interop.dart | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart b/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart index d5eaafd8b0ee..428e07e6f251 100644 --- a/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart +++ b/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart @@ -27,7 +27,7 @@ external FirestoreJsImpl initializeFirestore( @staticInterop /// Type DocumentReferenceJsImpl -external JSPromise addDoc( +external JSPromise addDoc( CollectionReferenceJsImpl reference, JSAny data, ); @@ -123,37 +123,37 @@ external JSPromise enableNetwork(FirestoreJsImpl firestore); @JS() @staticInterop -external JSPromise getDoc( +external JSPromise getDoc( DocumentReferenceJsImpl reference, ); @JS() @staticInterop -external JSPromise getDocFromCache( +external JSPromise getDocFromCache( DocumentReferenceJsImpl reference, ); @JS() @staticInterop -external JSPromise getDocFromServer( +external JSPromise getDocFromServer( DocumentReferenceJsImpl reference, ); @JS() @staticInterop -external JSPromise getDocs( +external JSPromise getDocs( QueryJsImpl query, ); @JS() @staticInterop -external JSPromise getDocsFromCache( +external JSPromise getDocsFromCache( QueryJsImpl query, ); @JS() @staticInterop -external JSPromise getDocsFromServer( +external JSPromise getDocsFromServer( QueryJsImpl query, ); From da357191bd7905ef7c3ac2344956ee1c3054e2b5 Mon Sep 17 00:00:00 2001 From: MichaelVerdon Date: Mon, 27 Oct 2025 12:51:47 +0000 Subject: [PATCH 3/5] fix: lint --- .../cloud_firestore_web/lib/src/interop/firestore.dart | 5 +++-- .../lib/src/interop/firestore_interop.dart | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore.dart b/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore.dart index 909a2df910ee..384eb6b92168 100644 --- a/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore.dart +++ b/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore.dart @@ -719,8 +719,9 @@ class CollectionReference return _expando[jsObject] ??= CollectionReference._fromJsObject(jsObject); } - factory CollectionReference(firestore_interop.CollectionReferenceJsImpl jsObject) => - CollectionReference._fromJsObject(jsObject); + factory CollectionReference( + firestore_interop.CollectionReferenceJsImpl jsObject) => + CollectionReference._fromJsObject(jsObject); CollectionReference._fromJsObject( firestore_interop.CollectionReferenceJsImpl jsObject) diff --git a/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart b/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart index 428e07e6f251..9d9fa0fdadf4 100644 --- a/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart +++ b/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart @@ -472,7 +472,6 @@ extension type DocumentChangeJsImpl._(JSObject _) implements JSObject { @staticInterop external DocumentReferenceJsImpl get DocumentReferenceJsConstructor; - extension type DocumentReferenceJsImpl._(JSObject _) implements JSObject { external FirestoreJsImpl get firestore; external JSString get id; @@ -758,7 +757,7 @@ extension type PersistentMultipleTabManager._(JSObject _) implements JSObject { } /// A garbage collector deletes documents whenever they are not part of any active queries, and have no local mutations attached to them. -/// +/// extension type MemoryEagerGarbageCollector._(JSObject _) implements JSObject { external JSString get kind; } @@ -829,7 +828,8 @@ extension PersistentCacheSettingsExtension on PersistentCacheSettings { /// An settings object to configure an PersistentLocalCache instance. /// /// See: . -extension type PersistentSingleTabManagerSettings._(JSObject _) implements JSObject { +extension type PersistentSingleTabManagerSettings._(JSObject _) + implements JSObject { /// Whether to force-enable persistent (IndexedDB) cache for the client. /// This cannot be used with multi-tab synchronization and is primarily /// intended for use with Web Workers. From 28c83154d88d03f80ee413f6ddcfd25856cce773 Mon Sep 17 00:00:00 2001 From: MichaelVerdon Date: Mon, 27 Oct 2025 12:56:22 +0000 Subject: [PATCH 4/5] fix: unneccesary cast --- .../cloud_firestore_web/lib/src/interop/firestore.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore.dart b/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore.dart index 384eb6b92168..d64c5f98cfeb 100644 --- a/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore.dart +++ b/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore.dart @@ -731,8 +731,7 @@ class CollectionReference final future = firestore_interop.addDoc(jsObject, jsify(data)! as JSObject).toDart; final result = await future; - return DocumentReference.getInstance( - (result)! as firestore_interop.DocumentReferenceJsImpl); + return DocumentReference.getInstance(result); } DocumentReference doc([String? documentPath]) { From d5e6a978f0448fc7d6ff21881dfffeb26423d3ea Mon Sep 17 00:00:00 2001 From: MichaelVerdon Date: Tue, 28 Oct 2025 14:33:02 +0000 Subject: [PATCH 5/5] chore: comment out lint error --- .../cloud_firestore/cloud_firestore_web/test/test_common.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/cloud_firestore/cloud_firestore_web/test/test_common.dart b/packages/cloud_firestore/cloud_firestore_web/test/test_common.dart index 2765bde96565..bf419dfed07d 100644 --- a/packages/cloud_firestore/cloud_firestore_web/test/test_common.dart +++ b/packages/cloud_firestore/cloud_firestore_web/test/test_common.dart @@ -14,7 +14,8 @@ const kCollectionId = 'test'; class MockWebDocumentSnapshot extends Mock implements web.DocumentSnapshot {} -class MockWebSnapshotMetaData extends Mock implements web.SnapshotMetadata {} +// Lint error here but tests pass without this. +// class MockWebSnapshotMetaData extends Mock implements web.SnapshotMetadata {} class MockFirestoreWeb extends Mock implements web.Firestore {}