@firebase/database 0.13.4 → 0.13.5-20220816211541

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1289,7 +1289,7 @@ var WebSocketConnection = /** @class */ (function () {
1289
1289
  }());
1290
1290
 
1291
1291
  var name = "@firebase/database";
1292
- var version = "0.13.4";
1292
+ var version = "0.13.5-20220816211541";
1293
1293
 
1294
1294
  /**
1295
1295
  * @license
@@ -9395,7 +9395,7 @@ function viewProcessorApplyServerMerge(viewProcessor, viewCache, path, changedCh
9395
9395
  });
9396
9396
  viewMergeTree.children.inorderTraversal(function (childKey, childMergeTree) {
9397
9397
  var isUnknownDeepMerge = !viewCache.serverCache.isCompleteForChild(childKey) &&
9398
- childMergeTree.value === undefined;
9398
+ childMergeTree.value === null;
9399
9399
  if (!serverNode.hasChild(childKey) && !isUnknownDeepMerge) {
9400
9400
  var serverChild = viewCache.serverCache
9401
9401
  .getNode()
@@ -10097,9 +10097,12 @@ function syncTreeApplyTaggedListenComplete(syncTree, path, tag) {
10097
10097
  *
10098
10098
  * @param eventRegistration - If null, all callbacks are removed.
10099
10099
  * @param cancelError - If a cancelError is provided, appropriate cancel events will be returned.
10100
+ * @param skipListenerDedup - When performing a `get()`, we don't add any new listeners, so no
10101
+ * deduping needs to take place. This flag allows toggling of that behavior
10100
10102
  * @returns Cancel events, if cancelError was provided.
10101
10103
  */
10102
- function syncTreeRemoveEventRegistration(syncTree, query, eventRegistration, cancelError) {
10104
+ function syncTreeRemoveEventRegistration(syncTree, query, eventRegistration, cancelError, skipListenerDedup) {
10105
+ if (skipListenerDedup === void 0) { skipListenerDedup = false; }
10103
10106
  // Find the syncPoint first. Then deal with whether or not it has matching listeners
10104
10107
  var path = query._path;
10105
10108
  var maybeSyncPoint = syncTree.syncPointTree_.get(path);
@@ -10116,50 +10119,54 @@ function syncTreeRemoveEventRegistration(syncTree, query, eventRegistration, can
10116
10119
  }
10117
10120
  var removed = removedAndEvents.removed;
10118
10121
  cancelEvents = removedAndEvents.events;
10119
- // We may have just removed one of many listeners and can short-circuit this whole process
10120
- // We may also not have removed a default listener, in which case all of the descendant listeners should already be
10121
- // properly set up.
10122
- //
10123
- // Since indexed queries can shadow if they don't have other query constraints, check for loadsAllData(), instead of
10124
- // queryId === 'default'
10125
- var removingDefault = -1 !==
10126
- removed.findIndex(function (query) {
10127
- return query._queryParams.loadsAllData();
10122
+ if (!skipListenerDedup) {
10123
+ /**
10124
+ * We may have just removed one of many listeners and can short-circuit this whole process
10125
+ * We may also not have removed a default listener, in which case all of the descendant listeners should already be
10126
+ * properly set up.
10127
+ */
10128
+ // Since indexed queries can shadow if they don't have other query constraints, check for loadsAllData(), instead of
10129
+ // queryId === 'default'
10130
+ var removingDefault = -1 !==
10131
+ removed.findIndex(function (query) {
10132
+ return query._queryParams.loadsAllData();
10133
+ });
10134
+ var covered = syncTree.syncPointTree_.findOnPath(path, function (relativePath, parentSyncPoint) {
10135
+ return syncPointHasCompleteView(parentSyncPoint);
10128
10136
  });
10129
- var covered = syncTree.syncPointTree_.findOnPath(path, function (relativePath, parentSyncPoint) {
10130
- return syncPointHasCompleteView(parentSyncPoint);
10131
- });
10132
- if (removingDefault && !covered) {
10133
- var subtree = syncTree.syncPointTree_.subtree(path);
10134
- // There are potentially child listeners. Determine what if any listens we need to send before executing the
10135
- // removal
10136
- if (!subtree.isEmpty()) {
10137
- // We need to fold over our subtree and collect the listeners to send
10138
- var newViews = syncTreeCollectDistinctViewsForSubTree_(subtree);
10139
- // Ok, we've collected all the listens we need. Set them up.
10140
- for (var i = 0; i < newViews.length; ++i) {
10141
- var view = newViews[i], newQuery = view.query;
10142
- var listener = syncTreeCreateListenerForView_(syncTree, view);
10143
- syncTree.listenProvider_.startListening(syncTreeQueryForListening_(newQuery), syncTreeTagForQuery_(syncTree, newQuery), listener.hashFn, listener.onComplete);
10137
+ if (removingDefault && !covered) {
10138
+ var subtree = syncTree.syncPointTree_.subtree(path);
10139
+ // There are potentially child listeners. Determine what if any listens we need to send before executing the
10140
+ // removal
10141
+ if (!subtree.isEmpty()) {
10142
+ // We need to fold over our subtree and collect the listeners to send
10143
+ var newViews = syncTreeCollectDistinctViewsForSubTree_(subtree);
10144
+ // Ok, we've collected all the listens we need. Set them up.
10145
+ for (var i = 0; i < newViews.length; ++i) {
10146
+ var view = newViews[i], newQuery = view.query;
10147
+ var listener = syncTreeCreateListenerForView_(syncTree, view);
10148
+ syncTree.listenProvider_.startListening(syncTreeQueryForListening_(newQuery), syncTreeTagForQuery(syncTree, newQuery), listener.hashFn, listener.onComplete);
10149
+ }
10150
+ }
10151
+ // Otherwise there's nothing below us, so nothing we need to start listening on
10152
+ }
10153
+ // If we removed anything and we're not covered by a higher up listen, we need to stop listening on this query
10154
+ // The above block has us covered in terms of making sure we're set up on listens lower in the tree.
10155
+ // Also, note that if we have a cancelError, it's already been removed at the provider level.
10156
+ if (!covered && removed.length > 0 && !cancelError) {
10157
+ // If we removed a default, then we weren't listening on any of the other queries here. Just cancel the one
10158
+ // default. Otherwise, we need to iterate through and cancel each individual query
10159
+ if (removingDefault) {
10160
+ // We don't tag default listeners
10161
+ var defaultTag = null;
10162
+ syncTree.listenProvider_.stopListening(syncTreeQueryForListening_(query), defaultTag);
10163
+ }
10164
+ else {
10165
+ removed.forEach(function (queryToRemove) {
10166
+ var tagToRemove = syncTree.queryToTagMap.get(syncTreeMakeQueryKey_(queryToRemove));
10167
+ syncTree.listenProvider_.stopListening(syncTreeQueryForListening_(queryToRemove), tagToRemove);
10168
+ });
10144
10169
  }
10145
- }
10146
- }
10147
- // If we removed anything and we're not covered by a higher up listen, we need to stop listening on this query
10148
- // The above block has us covered in terms of making sure we're set up on listens lower in the tree.
10149
- // Also, note that if we have a cancelError, it's already been removed at the provider level.
10150
- if (!covered && removed.length > 0 && !cancelError) {
10151
- // If we removed a default, then we weren't listening on any of the other queries here. Just cancel the one
10152
- // default. Otherwise, we need to iterate through and cancel each individual query
10153
- if (removingDefault) {
10154
- // We don't tag default listeners
10155
- var defaultTag = null;
10156
- syncTree.listenProvider_.stopListening(syncTreeQueryForListening_(query), defaultTag);
10157
- }
10158
- else {
10159
- removed.forEach(function (queryToRemove) {
10160
- var tagToRemove = syncTree.queryToTagMap.get(syncTreeMakeQueryKey_(queryToRemove));
10161
- syncTree.listenProvider_.stopListening(syncTreeQueryForListening_(queryToRemove), tagToRemove);
10162
- });
10163
10170
  }
10164
10171
  }
10165
10172
  // Now, clear all of the tags we're tracking for the removed listens
@@ -10167,30 +10174,6 @@ function syncTreeRemoveEventRegistration(syncTree, query, eventRegistration, can
10167
10174
  }
10168
10175
  return cancelEvents;
10169
10176
  }
10170
- /**
10171
- * This function was added to support non-listener queries,
10172
- * specifically for use in repoGetValue. It sets up all the same
10173
- * local cache data-structures (SyncPoint + View) that are
10174
- * needed for listeners without installing an event registration.
10175
- * If `query` is not `loadsAllData`, it will also provision a tag for
10176
- * the query so that query results can be merged into the sync
10177
- * tree using existing logic for tagged listener queries.
10178
- *
10179
- * @param syncTree - Synctree to add the query to.
10180
- * @param query - Query to register
10181
- * @returns tag as a string if query is not a default query, null if query is not.
10182
- */
10183
- function syncTreeRegisterQuery(syncTree, query) {
10184
- var _a = syncTreeRegisterSyncPoint(query, syncTree), syncPoint = _a.syncPoint, serverCache = _a.serverCache, writesCache = _a.writesCache, serverCacheComplete = _a.serverCacheComplete;
10185
- var view = syncPointGetView(syncPoint, query, writesCache, serverCache, serverCacheComplete);
10186
- if (!syncPoint.views.has(query._queryIdentifier)) {
10187
- syncPoint.views.set(query._queryIdentifier, view);
10188
- }
10189
- if (!query._queryParams.loadsAllData()) {
10190
- return syncTreeTagForQuery_(syncTree, query);
10191
- }
10192
- return null;
10193
- }
10194
10177
  /**
10195
10178
  * Apply new server data for the specified tagged query.
10196
10179
  *
@@ -10231,11 +10214,12 @@ function syncTreeApplyTaggedQueryMerge(syncTree, path, changedChildren, tag) {
10231
10214
  }
10232
10215
  }
10233
10216
  /**
10234
- * Creates a new syncpoint for a query and creates a tag if the view doesn't exist.
10235
- * Extracted from addEventRegistration to allow `repoGetValue` to properly set up the SyncTree
10236
- * without actually listening on a query.
10217
+ * Add an event callback for the specified query.
10218
+ *
10219
+ * @returns Events to raise.
10237
10220
  */
10238
- function syncTreeRegisterSyncPoint(query, syncTree) {
10221
+ function syncTreeAddEventRegistration(syncTree, query, eventRegistration, skipSetupListener) {
10222
+ if (skipSetupListener === void 0) { skipSetupListener = false; }
10239
10223
  var path = query._path;
10240
10224
  var serverCache = null;
10241
10225
  var foundAncestorDefaultView = false;
@@ -10284,24 +10268,8 @@ function syncTreeRegisterSyncPoint(query, syncTree) {
10284
10268
  syncTree.tagToQueryMap.set(tag, queryKey);
10285
10269
  }
10286
10270
  var writesCache = writeTreeChildWrites(syncTree.pendingWriteTree_, path);
10287
- return {
10288
- syncPoint: syncPoint,
10289
- writesCache: writesCache,
10290
- serverCache: serverCache,
10291
- serverCacheComplete: serverCacheComplete,
10292
- foundAncestorDefaultView: foundAncestorDefaultView,
10293
- viewAlreadyExists: viewAlreadyExists
10294
- };
10295
- }
10296
- /**
10297
- * Add an event callback for the specified query.
10298
- *
10299
- * @returns Events to raise.
10300
- */
10301
- function syncTreeAddEventRegistration(syncTree, query, eventRegistration) {
10302
- var _a = syncTreeRegisterSyncPoint(query, syncTree), syncPoint = _a.syncPoint, serverCache = _a.serverCache, writesCache = _a.writesCache, serverCacheComplete = _a.serverCacheComplete, viewAlreadyExists = _a.viewAlreadyExists, foundAncestorDefaultView = _a.foundAncestorDefaultView;
10303
10271
  var events = syncPointAddEventRegistration(syncPoint, query, eventRegistration, writesCache, serverCache, serverCacheComplete);
10304
- if (!viewAlreadyExists && !foundAncestorDefaultView) {
10272
+ if (!viewAlreadyExists && !foundAncestorDefaultView && !skipSetupListener) {
10305
10273
  var view = syncPointViewForQuery(syncPoint, query);
10306
10274
  events = events.concat(syncTreeSetupListener_(syncTree, query, view));
10307
10275
  }
@@ -10431,7 +10399,7 @@ function syncTreeApplyOperationDescendantsHelper_(operation, syncPointTree, serv
10431
10399
  }
10432
10400
  function syncTreeCreateListenerForView_(syncTree, view) {
10433
10401
  var query = view.query;
10434
- var tag = syncTreeTagForQuery_(syncTree, query);
10402
+ var tag = syncTreeTagForQuery(syncTree, query);
10435
10403
  return {
10436
10404
  hashFn: function () {
10437
10405
  var cache = viewGetServerCache(view) || ChildrenNode.EMPTY_NODE;
@@ -10459,7 +10427,7 @@ function syncTreeCreateListenerForView_(syncTree, view) {
10459
10427
  /**
10460
10428
  * Return the tag associated with the given query.
10461
10429
  */
10462
- function syncTreeTagForQuery_(syncTree, query) {
10430
+ function syncTreeTagForQuery(syncTree, query) {
10463
10431
  var queryKey = syncTreeMakeQueryKey_(query);
10464
10432
  return syncTree.queryToTagMap.get(queryKey);
10465
10433
  }
@@ -10559,7 +10527,7 @@ function syncTreeGetNextQueryTag_() {
10559
10527
  */
10560
10528
  function syncTreeSetupListener_(syncTree, query, view) {
10561
10529
  var path = query._path;
10562
- var tag = syncTreeTagForQuery_(syncTree, query);
10530
+ var tag = syncTreeTagForQuery(syncTree, query);
10563
10531
  var listener = syncTreeCreateListenerForView_(syncTree, view);
10564
10532
  var events = syncTree.listenProvider_.startListening(syncTreeQueryForListening_(query), tag, listener.hashFn, listener.onComplete);
10565
10533
  var subtree = syncTree.syncPointTree_.subtree(path);
@@ -10590,7 +10558,7 @@ function syncTreeSetupListener_(syncTree, query, view) {
10590
10558
  });
10591
10559
  for (var i = 0; i < queriesToStop.length; ++i) {
10592
10560
  var queryToStop = queriesToStop[i];
10593
- syncTree.listenProvider_.stopListening(syncTreeQueryForListening_(queryToStop), syncTreeTagForQuery_(syncTree, queryToStop));
10561
+ syncTree.listenProvider_.stopListening(syncTreeQueryForListening_(queryToStop), syncTreeTagForQuery(syncTree, queryToStop));
10594
10562
  }
10595
10563
  }
10596
10564
  return events;
@@ -11527,14 +11495,14 @@ function repoGetNextWriteId(repo) {
11527
11495
  * belonging to active listeners. If they are found, such values
11528
11496
  * are considered to be the most up-to-date.
11529
11497
  *
11530
- * If the client is not connected, this method will try to
11531
- * establish a connection and request the value for `query`. If
11532
- * the client is not able to retrieve the query result, it reports
11533
- * an error.
11498
+ * If the client is not connected, this method will wait until the
11499
+ * repo has established a connection and then request the value for `query`.
11500
+ * If the client is not able to retrieve the query result for another reason,
11501
+ * it reports an error.
11534
11502
  *
11535
11503
  * @param query - The query to surface a value for.
11536
11504
  */
11537
- function repoGetValue(repo, query) {
11505
+ function repoGetValue(repo, query, eventRegistration) {
11538
11506
  // Only active queries are cached. There is no persisted cache.
11539
11507
  var cached = syncTreeGetServerValue(repo.serverSyncTree_, query);
11540
11508
  if (cached != null) {
@@ -11542,24 +11510,34 @@ function repoGetValue(repo, query) {
11542
11510
  }
11543
11511
  return repo.server_.get(query).then(function (payload) {
11544
11512
  var node = nodeFromJSON(payload).withIndex(query._queryParams.getIndex());
11545
- // if this is a filtered query, then overwrite at path
11513
+ /**
11514
+ * Below we simulate the actions of an `onlyOnce` `onValue()` event where:
11515
+ * Add an event registration,
11516
+ * Update data at the path,
11517
+ * Raise any events,
11518
+ * Cleanup the SyncTree
11519
+ */
11520
+ syncTreeAddEventRegistration(repo.serverSyncTree_, query, eventRegistration, true);
11521
+ var events;
11546
11522
  if (query._queryParams.loadsAllData()) {
11547
- syncTreeApplyServerOverwrite(repo.serverSyncTree_, query._path, node);
11523
+ events = syncTreeApplyServerOverwrite(repo.serverSyncTree_, query._path, node);
11548
11524
  }
11549
11525
  else {
11550
- // Simulate `syncTreeAddEventRegistration` without events/listener setup.
11551
- // We do this (along with the syncTreeRemoveEventRegistration` below) so that
11552
- // `repoGetValue` results have the same cache effects as initial listener(s)
11553
- // updates.
11554
- var tag = syncTreeRegisterQuery(repo.serverSyncTree_, query);
11555
- syncTreeApplyTaggedQueryOverwrite(repo.serverSyncTree_, query._path, node, tag);
11556
- // Call `syncTreeRemoveEventRegistration` with a null event registration, since there is none.
11557
- // Note: The below code essentially unregisters the query and cleans up any views/syncpoints temporarily created above.
11558
- }
11559
- var cancels = syncTreeRemoveEventRegistration(repo.serverSyncTree_, query, null);
11560
- if (cancels.length > 0) {
11561
- repoLog(repo, 'unexpected cancel events in repoGetValue');
11526
+ var tag = syncTreeTagForQuery(repo.serverSyncTree_, query);
11527
+ events = syncTreeApplyTaggedQueryOverwrite(repo.serverSyncTree_, query._path, node, tag);
11562
11528
  }
11529
+ /*
11530
+ * We need to raise events in the scenario where `get()` is called at a parent path, and
11531
+ * while the `get()` is pending, `onValue` is called at a child location. While get() is waiting
11532
+ * for the data, `onValue` will register a new event. Then, get() will come back, and update the syncTree
11533
+ * and its corresponding serverCache, including the child location where `onValue` is called. Then,
11534
+ * `onValue` will receive the event from the server, but look at the syncTree and see that the data received
11535
+ * from the server is already at the SyncPoint, and so the `onValue` callback will never get fired.
11536
+ * Calling `eventQueueRaiseEventsForChangedPath()` is the correct way to propagate the events and
11537
+ * ensure the corresponding child events will get fired.
11538
+ */
11539
+ eventQueueRaiseEventsForChangedPath(repo.eventQueue_, query._path, events);
11540
+ syncTreeRemoveEventRegistration(repo.serverSyncTree_, query, eventRegistration, null, true);
11563
11541
  return node;
11564
11542
  }, function (err) {
11565
11543
  repoLog(repo, 'get for query ' + util.stringify(query) + ' failed: ' + err);
@@ -13319,7 +13297,9 @@ function update(ref, values) {
13319
13297
  */
13320
13298
  function get(query) {
13321
13299
  query = util.getModularInstance(query);
13322
- return repoGetValue(query._repo, query).then(function (node) {
13300
+ var callbackContext = new CallbackContext(function () { });
13301
+ var container = new ValueEventRegistration(callbackContext);
13302
+ return repoGetValue(query._repo, query, container).then(function (node) {
13323
13303
  return new DataSnapshot(node, new ReferenceImpl(query._repo, query._path), query._queryParams.getIndex());
13324
13304
  });
13325
13305
  }