From 94d848068aa39ec639327232e864b25546fbed9b Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 6 Jun 2024 16:24:37 +0100 Subject: [PATCH 1/8] fix(database, web): clean up stream handlers on "hot restart" --- .../lib/src/interop/database.dart | 54 ++++++++++++------- .../lib/src/interop/database_interop.dart | 10 ++-- .../lib/src/query_web.dart | 22 ++++++-- 3 files changed, 57 insertions(+), 29 deletions(-) diff --git a/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart b/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart index da65bbd518ee..23cd482bc611 100755 --- a/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart +++ b/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart @@ -251,37 +251,47 @@ class Query extends JsObjectWrapper { /// DatabaseReference to the Query's location. DatabaseReference get ref => DatabaseReference.getInstance(jsObject.ref); - late final Stream _onValue = _createStream('value'); + Stream _onValue(int hashCode) => _createStream('value', hashCode); /// Stream for a value event. Event is triggered once with the initial /// data stored at location, and then again each time the data changes. - Stream get onValue => _onValue; + Stream onValue(int hashCode) => _onValue(hashCode); - late final Stream _onChildAdded = _createStream('child_added'); + Stream _onChildAdded(int hashCode) => _createStream( + 'child_added', + hashCode, + ); /// Stream for a child_added event. Event is triggered once for each /// initial child at location, and then again every time a new child is added. - Stream get onChildAdded => _onChildAdded; + Stream onChildAdded(int hashCode) => _onChildAdded(hashCode); - late final Stream _onChildRemoved = - _createStream('child_removed'); + Stream _onChildRemoved(int hashCode) => _createStream( + 'child_removed', + hashCode, + ); /// Stream for a child_removed event. Event is triggered once every time /// a child is removed. - Stream get onChildRemoved => _onChildRemoved; + Stream onChildRemoved(int hashCode) => _onChildRemoved(hashCode); - late final Stream _onChildChanged = - _createStream('child_changed'); + Stream _onChildChanged(int hashCode) => _createStream( + 'child_changed', + hashCode, + ); /// Stream for a child_changed event. Event is triggered when the data /// stored in a child (or any of its descendants) changes. /// Single child_changed event may represent multiple changes to the child. - Stream get onChildChanged => _onChildChanged; - late final Stream _onChildMoved = _createStream('child_moved'); + Stream onChildChanged(int hashCode) => _onChildChanged(hashCode); + Stream _onChildMoved(int hashCode) => _createStream( + 'child_moved', + hashCode, + ); /// Stream for a child_moved event. Event is triggered when a child's priority /// changes such that its position relative to its siblings changes. - Stream get onChildMoved => _onChildMoved; + Stream onChildMoved(int hashCode) => _onChildMoved(hashCode); /// Creates a new Query from a [jsObject]. Query.fromJsObject(T jsObject) : super.fromJsObject(jsObject); @@ -376,10 +386,13 @@ class Query extends JsObjectWrapper { ), ); } + // TODO - get appName + String _streamWindowsKey(String eventType, int hashCode) => + 'flutterfire-${eventType}_${hashCode}_documentSnapshot'; - Stream _createStream(String eventType) { + Stream _createStream(String eventType, int hashCode) { late StreamController streamController; - + unsubscribeWindowsListener(_streamWindowsKey(eventType, hashCode)); final callbackWrap = (( database_interop.DataSnapshotJsImpl data, [ String? string, @@ -393,45 +406,48 @@ class Query extends JsObjectWrapper { }); void startListen() { + var unsubscribe; if (eventType == 'child_added') { - database_interop.onChildAdded( + unsubscribe = database_interop.onChildAdded( jsObject, callbackWrap.toJS, cancelCallbackWrap.toJS, ); } if (eventType == 'value') { - database_interop.onValue( + unsubscribe = database_interop.onValue( jsObject, callbackWrap.toJS, cancelCallbackWrap.toJS, ); } if (eventType == 'child_removed') { - database_interop.onChildRemoved( + unsubscribe = database_interop.onChildRemoved( jsObject, callbackWrap.toJS, cancelCallbackWrap.toJS, ); } if (eventType == 'child_changed') { - database_interop.onChildChanged( + unsubscribe = database_interop.onChildChanged( jsObject, callbackWrap.toJS, cancelCallbackWrap.toJS, ); } if (eventType == 'child_moved') { - database_interop.onChildMoved( + unsubscribe = database_interop.onChildMoved( jsObject, callbackWrap.toJS, cancelCallbackWrap.toJS, ); } + setWindowsListener(_streamWindowsKey(eventType, hashCode), unsubscribe); } void stopListen() { database_interop.off(jsObject, eventType.toJS, callbackWrap.toJS); + removeWindowsListener(_streamWindowsKey(eventType, hashCode)); } streamController = StreamController.broadcast( diff --git a/packages/firebase_database/firebase_database_web/lib/src/interop/database_interop.dart b/packages/firebase_database/firebase_database_web/lib/src/interop/database_interop.dart index fcc610e10a3d..534666551e45 100755 --- a/packages/firebase_database/firebase_database_web/lib/src/interop/database_interop.dart +++ b/packages/firebase_database/firebase_database_web/lib/src/interop/database_interop.dart @@ -79,7 +79,7 @@ external void off([ @JS() @staticInterop -external QueryConstraintJsImpl onChildAdded( +external JSFunction onChildAdded( QueryJsImpl query, JSFunction callback, // JSAny Function(DataSnapshotJsImpl, [JSString previousChildName]) callback, @@ -89,7 +89,7 @@ external QueryConstraintJsImpl onChildAdded( @JS() @staticInterop -external QueryConstraintJsImpl onChildChanged( +external JSFunction onChildChanged( QueryJsImpl query, JSFunction callback, // JSAny Function(DataSnapshotJsImpl, [JSString previousChildName]) callback, @@ -99,7 +99,7 @@ external QueryConstraintJsImpl onChildChanged( @JS() @staticInterop -external QueryConstraintJsImpl onChildMoved( +external JSFunction onChildMoved( QueryJsImpl query, JSFunction callback, // JSAny Function(DataSnapshotJsImpl, [JSString previousChildName]) callback, @@ -109,7 +109,7 @@ external QueryConstraintJsImpl onChildMoved( @JS() @staticInterop -external QueryConstraintJsImpl onChildRemoved( +external JSFunction onChildRemoved( QueryJsImpl query, JSFunction callback, // JSAny Function(DataSnapshotJsImpl, [JSString previousChildName]) callback, @@ -123,7 +123,7 @@ external OnDisconnectJsImpl onDisconnect(ReferenceJsImpl ref); @JS() @staticInterop -external void onValue( +external JSFunction onValue( QueryJsImpl query, JSFunction callback, // JSAny Function(DataSnapshotJsImpl, [JSString previousChildName]) callback, diff --git a/packages/firebase_database/firebase_database_web/lib/src/query_web.dart b/packages/firebase_database/firebase_database_web/lib/src/query_web.dart index 6bfeb999b3b2..cfc14f667c59 100755 --- a/packages/firebase_database/firebase_database_web/lib/src/query_web.dart +++ b/packages/firebase_database/firebase_database_web/lib/src/query_web.dart @@ -94,29 +94,41 @@ class QueryWeb extends QueryPlatform { QueryModifiers modifiers, DatabaseEventType eventType) { database_interop.Query instance = _getQueryDelegateInstance(modifiers); + final hashCode = Object.hash( + runtimeType, + database, + path, + instance, + eventType, + modifiers, + ); + switch (eventType) { case DatabaseEventType.childAdded: return _webStreamToPlatformStream( eventType, - instance.onChildAdded, + instance.onChildAdded(hashCode), ); case DatabaseEventType.childChanged: return _webStreamToPlatformStream( eventType, - instance.onChildChanged, + instance.onChildChanged(hashCode), ); case DatabaseEventType.childMoved: return _webStreamToPlatformStream( eventType, - instance.onChildMoved, + instance.onChildMoved(hashCode), ); case DatabaseEventType.childRemoved: return _webStreamToPlatformStream( eventType, - instance.onChildRemoved, + instance.onChildRemoved(hashCode), ); case DatabaseEventType.value: - return _webStreamToPlatformStream(eventType, instance.onValue); + return _webStreamToPlatformStream( + eventType, + instance.onValue(hashCode), + ); default: throw Exception("Invalid event type: $eventType"); } From faec086b6f0e2c72046738478afc725a68ba6ee5 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 7 Jun 2024 13:28:19 +0100 Subject: [PATCH 2/8] fix(database, web): stream handling --- .../lib/firebase_database_web.dart | 3 +- .../lib/src/interop/database.dart | 92 +++++++++++++------ .../lib/src/interop/database_interop.dart | 15 +-- .../lib/src/query_web.dart | 49 +++++++--- 4 files changed, 102 insertions(+), 57 deletions(-) diff --git a/packages/firebase_database/firebase_database_web/lib/firebase_database_web.dart b/packages/firebase_database/firebase_database_web/lib/firebase_database_web.dart index 8a9b681c787d..1062e9ca655e 100755 --- a/packages/firebase_database/firebase_database_web/lib/firebase_database_web.dart +++ b/packages/firebase_database/firebase_database_web/lib/firebase_database_web.dart @@ -6,12 +6,13 @@ library firebase_database_web; import 'dart:async'; import 'dart:js_interop'; - +import 'package:collection/collection.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core_web/firebase_core_web.dart'; import 'package:firebase_core_web/firebase_core_web_interop.dart' as core_interop; import 'package:firebase_database_platform_interface/firebase_database_platform_interface.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter_web_plugins/flutter_web_plugins.dart'; import 'src/interop/database.dart' as database_interop; diff --git a/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart b/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart index 23cd482bc611..39667ace3b77 100755 --- a/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart +++ b/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart @@ -226,6 +226,7 @@ class DatabaseReference /// DataSnapshot dataSnapshot = e.snapshot; /// //... /// }); +// TODO maybe it is the wrong one? class QueryEvent { /// Immutable copy of the data at a database location. final DataSnapshot snapshot; @@ -251,47 +252,64 @@ class Query extends JsObjectWrapper { /// DatabaseReference to the Query's location. DatabaseReference get ref => DatabaseReference.getInstance(jsObject.ref); - Stream _onValue(int hashCode) => _createStream('value', hashCode); + Stream _onValue(String appName, int hashCode) => _createStream( + 'value', + appName, + hashCode, + ); /// Stream for a value event. Event is triggered once with the initial /// data stored at location, and then again each time the data changes. - Stream onValue(int hashCode) => _onValue(hashCode); + Stream onValue(String appName, int hashCode) => + _onValue(appName, hashCode); - Stream _onChildAdded(int hashCode) => _createStream( + Stream _onChildAdded(String appName, int hashCode) => + _createStream( 'child_added', + appName, hashCode, ); /// Stream for a child_added event. Event is triggered once for each /// initial child at location, and then again every time a new child is added. - Stream onChildAdded(int hashCode) => _onChildAdded(hashCode); + Stream onChildAdded(String appName, int hashCode) => + _onChildAdded(appName, hashCode); - Stream _onChildRemoved(int hashCode) => _createStream( + Stream _onChildRemoved(String appName, int hashCode) => + _createStream( 'child_removed', + appName, hashCode, ); /// Stream for a child_removed event. Event is triggered once every time /// a child is removed. - Stream onChildRemoved(int hashCode) => _onChildRemoved(hashCode); + Stream onChildRemoved(String appName, int hashCode) => + _onChildRemoved(appName, hashCode); - Stream _onChildChanged(int hashCode) => _createStream( + Stream _onChildChanged(String appName, int hashCode) => + _createStream( 'child_changed', + appName, hashCode, ); /// Stream for a child_changed event. Event is triggered when the data /// stored in a child (or any of its descendants) changes. /// Single child_changed event may represent multiple changes to the child. - Stream onChildChanged(int hashCode) => _onChildChanged(hashCode); - Stream _onChildMoved(int hashCode) => _createStream( + Stream onChildChanged(String appName, int hashCode) => + _onChildChanged(appName, hashCode); + Stream _onChildMoved(String appName, int hashCode) => + _createStream( 'child_moved', + appName, hashCode, ); /// Stream for a child_moved event. Event is triggered when a child's priority /// changes such that its position relative to its siblings changes. - Stream onChildMoved(int hashCode) => _onChildMoved(hashCode); + Stream onChildMoved(String appName, int hashCode) => + _onChildMoved(appName, hashCode); /// Creates a new Query from a [jsObject]. Query.fromJsObject(T jsObject) : super.fromJsObject(jsObject); @@ -386,73 +404,89 @@ class Query extends JsObjectWrapper { ), ); } - // TODO - get appName - String _streamWindowsKey(String eventType, int hashCode) => - 'flutterfire-${eventType}_${hashCode}_documentSnapshot'; - Stream _createStream(String eventType, int hashCode) { + String _streamWindowsKey(String appName, String eventType, int hashCode) => + 'flutterfire-${appName}_${eventType}_${hashCode}_snapshot'; + + Stream _createStream( + String eventType, + String appName, + int hashCode, + ) { late StreamController streamController; - unsubscribeWindowsListener(_streamWindowsKey(eventType, hashCode)); + unsubscribeWindowsListener(_streamWindowsKey(appName, eventType, hashCode)); final callbackWrap = (( database_interop.DataSnapshotJsImpl data, [ - String? string, + String? prevChild, ]) { - streamController.add(QueryEvent(DataSnapshot.getInstance(data), string)); + if (!streamController.isClosed) { + streamController + .add(QueryEvent(DataSnapshot.getInstance(data), prevChild)); + } }); final void Function(JSObject) cancelCallbackWrap = ((JSObject error) { streamController.addError(convertFirebaseDatabaseException(error)); - streamController.close(); }); + late JSFunction onUnsubscribe; + void startListen() { - var unsubscribe; if (eventType == 'child_added') { - unsubscribe = database_interop.onChildAdded( + onUnsubscribe = database_interop.onChildAdded( jsObject, callbackWrap.toJS, cancelCallbackWrap.toJS, ); } if (eventType == 'value') { - unsubscribe = database_interop.onValue( + onUnsubscribe = database_interop.onValue( jsObject, callbackWrap.toJS, cancelCallbackWrap.toJS, ); } if (eventType == 'child_removed') { - unsubscribe = database_interop.onChildRemoved( + //change callback, only snap + onUnsubscribe = database_interop.onChildRemoved( jsObject, callbackWrap.toJS, cancelCallbackWrap.toJS, ); } if (eventType == 'child_changed') { - unsubscribe = database_interop.onChildChanged( + onUnsubscribe = database_interop.onChildChanged( jsObject, callbackWrap.toJS, cancelCallbackWrap.toJS, ); } if (eventType == 'child_moved') { - unsubscribe = database_interop.onChildMoved( + onUnsubscribe = database_interop.onChildMoved( jsObject, callbackWrap.toJS, cancelCallbackWrap.toJS, ); } - setWindowsListener(_streamWindowsKey(eventType, hashCode), unsubscribe); + setWindowsListener( + _streamWindowsKey(appName, eventType, hashCode), + onUnsubscribe, + ); } void stopListen() { - database_interop.off(jsObject, eventType.toJS, callbackWrap.toJS); - removeWindowsListener(_streamWindowsKey(eventType, hashCode)); + onUnsubscribe.callAsFunction(); + removeWindowsListener(_streamWindowsKey( + appName, + eventType, + hashCode, + )); } streamController = StreamController.broadcast( onListen: startListen, onCancel: stopListen, + sync: true, ); return streamController.stream; } @@ -463,8 +497,8 @@ class Query extends JsObjectWrapper { database_interop.onValue( jsObject, - ((database_interop.DataSnapshotJsImpl snapshot, [String? string]) { - c.complete(QueryEvent(DataSnapshot.getInstance(snapshot), string)); + ((database_interop.DataSnapshotJsImpl snapshot, [String? prevChild]) { + c.complete(QueryEvent(DataSnapshot.getInstance(snapshot), prevChild)); }).toJS, ((JSAny error) { c.completeError(convertFirebaseDatabaseException(error)); diff --git a/packages/firebase_database/firebase_database_web/lib/src/interop/database_interop.dart b/packages/firebase_database/firebase_database_web/lib/src/interop/database_interop.dart index 534666551e45..9d7dcd308aa6 100755 --- a/packages/firebase_database/firebase_database_web/lib/src/interop/database_interop.dart +++ b/packages/firebase_database/firebase_database_web/lib/src/interop/database_interop.dart @@ -68,15 +68,6 @@ external void goOnline(DatabaseJsImpl database); @staticInterop external JSAny increment(JSNumber delta); -@JS() -@staticInterop -external void off([ - QueryJsImpl query, - JSString eventType, - JSFunction callback, - /*JSAny Function(DataSnapshotJsImpl, [JSString previousChildName]) callback*/ -]); - @JS() @staticInterop external JSFunction onChildAdded( @@ -124,11 +115,7 @@ external OnDisconnectJsImpl onDisconnect(ReferenceJsImpl ref); @JS() @staticInterop external JSFunction onValue( - QueryJsImpl query, - JSFunction callback, - // JSAny Function(DataSnapshotJsImpl, [JSString previousChildName]) callback, - JSFunction cancelCallback, - // JSAny Function(FirebaseError error) cancelCallback, + QueryJsImpl query, JSFunction callback, JSFunction cancelCallback, [ListenOptions options]); @JS() diff --git a/packages/firebase_database/firebase_database_web/lib/src/query_web.dart b/packages/firebase_database/firebase_database_web/lib/src/query_web.dart index cfc14f667c59..4811fd306256 100755 --- a/packages/firebase_database/firebase_database_web/lib/src/query_web.dart +++ b/packages/firebase_database/firebase_database_web/lib/src/query_web.dart @@ -94,40 +94,63 @@ class QueryWeb extends QueryPlatform { QueryModifiers modifiers, DatabaseEventType eventType) { database_interop.Query instance = _getQueryDelegateInstance(modifiers); - final hashCode = Object.hash( - runtimeType, - database, - path, - instance, - eventType, - modifiers, - ); + int hashCode = 0; + final appName = + _database.app != null ? _database.app!.name : Firebase.app().name; + if (kDebugMode) { + // Purely for unsubscribing purposes in debug mode on "hot restart" + // if not running in debug mode, hashCode won't be used + hashCode = Object.hashAll([ + appName, + path, + ...modifiers + .toList() + .map((e) => const DeepCollectionEquality().hash(e)) + .toList(), + eventType.index, + ]); + } switch (eventType) { case DatabaseEventType.childAdded: return _webStreamToPlatformStream( eventType, - instance.onChildAdded(hashCode), + instance.onChildAdded( + appName, + hashCode, + ), ); case DatabaseEventType.childChanged: return _webStreamToPlatformStream( eventType, - instance.onChildChanged(hashCode), + instance.onChildChanged( + appName, + hashCode, + ), ); case DatabaseEventType.childMoved: return _webStreamToPlatformStream( eventType, - instance.onChildMoved(hashCode), + instance.onChildMoved( + appName, + hashCode, + ), ); case DatabaseEventType.childRemoved: return _webStreamToPlatformStream( eventType, - instance.onChildRemoved(hashCode), + instance.onChildRemoved( + appName, + hashCode, + ), ); case DatabaseEventType.value: return _webStreamToPlatformStream( eventType, - instance.onValue(hashCode), + instance.onValue( + appName, + hashCode, + ), ); default: throw Exception("Invalid event type: $eventType"); From 01097080f8f2249aadbb2d15b1ed0b152e9877c8 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 7 Jun 2024 13:44:19 +0100 Subject: [PATCH 3/8] chore: rm comment --- .../firebase_database_web/lib/src/interop/database.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart b/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart index 39667ace3b77..e2580c0056bb 100755 --- a/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart +++ b/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart @@ -226,7 +226,6 @@ class DatabaseReference /// DataSnapshot dataSnapshot = e.snapshot; /// //... /// }); -// TODO maybe it is the wrong one? class QueryEvent { /// Immutable copy of the data at a database location. final DataSnapshot snapshot; From 021e8d6314cc164c50a8e8c5200cf64ec6040da0 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 7 Jun 2024 13:44:43 +0100 Subject: [PATCH 4/8] chore: add collection dep --- packages/firebase_database/firebase_database_web/pubspec.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/firebase_database/firebase_database_web/pubspec.yaml b/packages/firebase_database/firebase_database_web/pubspec.yaml index 091100bf48d8..81b185f58829 100644 --- a/packages/firebase_database/firebase_database_web/pubspec.yaml +++ b/packages/firebase_database/firebase_database_web/pubspec.yaml @@ -8,6 +8,7 @@ environment: flutter: '>=3.3.0' dependencies: + collection: ^1.18.0 firebase_core: ^3.0.0 firebase_core_web: ^2.17.1 firebase_database_platform_interface: ^0.2.5+36 From 3c6e9eebf8cc676b1a9dc2bd31f5906d12ff9ebf Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 7 Jun 2024 13:55:12 +0100 Subject: [PATCH 5/8] chore: remove unneeded check --- .../firebase_database_web/lib/src/interop/database.dart | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart b/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart index e2580c0056bb..9a7c1a967ead 100755 --- a/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart +++ b/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart @@ -418,10 +418,8 @@ class Query extends JsObjectWrapper { database_interop.DataSnapshotJsImpl data, [ String? prevChild, ]) { - if (!streamController.isClosed) { - streamController - .add(QueryEvent(DataSnapshot.getInstance(data), prevChild)); - } + streamController + .add(QueryEvent(DataSnapshot.getInstance(data), prevChild)); }); final void Function(JSObject) cancelCallbackWrap = ((JSObject error) { From 015d118e0f1cbdfbfb0848ffc43eb05b52b4742b Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 7 Jun 2024 13:56:27 +0100 Subject: [PATCH 6/8] chore: remove comment --- .../firebase_database_web/lib/src/interop/database.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart b/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart index 9a7c1a967ead..1f83484c5c2a 100755 --- a/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart +++ b/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart @@ -444,7 +444,6 @@ class Query extends JsObjectWrapper { ); } if (eventType == 'child_removed') { - //change callback, only snap onUnsubscribe = database_interop.onChildRemoved( jsObject, callbackWrap.toJS, From 9e009dd34e7714976e1c6a3fa4198c954c3a7928 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 7 Jun 2024 13:59:46 +0100 Subject: [PATCH 7/8] chore: reinsert code comments --- .../lib/src/interop/database_interop.dart | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/firebase_database/firebase_database_web/lib/src/interop/database_interop.dart b/packages/firebase_database/firebase_database_web/lib/src/interop/database_interop.dart index 9d7dcd308aa6..a2c588adfeed 100755 --- a/packages/firebase_database/firebase_database_web/lib/src/interop/database_interop.dart +++ b/packages/firebase_database/firebase_database_web/lib/src/interop/database_interop.dart @@ -115,8 +115,14 @@ external OnDisconnectJsImpl onDisconnect(ReferenceJsImpl ref); @JS() @staticInterop external JSFunction onValue( - QueryJsImpl query, JSFunction callback, JSFunction cancelCallback, - [ListenOptions options]); + QueryJsImpl query, + JSFunction callback, + // JSAny Function(DataSnapshotJsImpl, [JSString previousChildName]) callback, + JSFunction cancelCallback, + // JSAny Function(FirebaseError error) cancelCallback, + [ + ListenOptions options, +]); @JS() @staticInterop From af3b2a5128e8f449eb9144122b575763720e25ed Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 7 Jun 2024 14:52:33 +0100 Subject: [PATCH 8/8] chore: remember to close stream once no listeners --- .../firebase_database_web/lib/src/interop/database.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart b/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart index 1f83484c5c2a..1c222461bf4a 100755 --- a/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart +++ b/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart @@ -472,6 +472,7 @@ class Query extends JsObjectWrapper { void stopListen() { onUnsubscribe.callAsFunction(); + streamController.close(); removeWindowsListener(_streamWindowsKey( appName, eventType,