@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.
@@ -5,7 +5,7 @@ import { __spreadArray, __read, __values, __extends, __awaiter, __generator, __a
5
5
  import { Logger, LogLevel } from '@firebase/logger';
6
6
 
7
7
  var name = "@firebase/database";
8
- var version = "0.13.4";
8
+ var version = "0.13.5-20220816211541";
9
9
 
10
10
  /**
11
11
  * @license
@@ -9383,7 +9383,7 @@ function viewProcessorApplyServerMerge(viewProcessor, viewCache, path, changedCh
9383
9383
  });
9384
9384
  viewMergeTree.children.inorderTraversal(function (childKey, childMergeTree) {
9385
9385
  var isUnknownDeepMerge = !viewCache.serverCache.isCompleteForChild(childKey) &&
9386
- childMergeTree.value === undefined;
9386
+ childMergeTree.value === null;
9387
9387
  if (!serverNode.hasChild(childKey) && !isUnknownDeepMerge) {
9388
9388
  var serverChild = viewCache.serverCache
9389
9389
  .getNode()
@@ -10085,9 +10085,12 @@ function syncTreeApplyTaggedListenComplete(syncTree, path, tag) {
10085
10085
  *
10086
10086
  * @param eventRegistration - If null, all callbacks are removed.
10087
10087
  * @param cancelError - If a cancelError is provided, appropriate cancel events will be returned.
10088
+ * @param skipListenerDedup - When performing a `get()`, we don't add any new listeners, so no
10089
+ * deduping needs to take place. This flag allows toggling of that behavior
10088
10090
  * @returns Cancel events, if cancelError was provided.
10089
10091
  */
10090
- function syncTreeRemoveEventRegistration(syncTree, query, eventRegistration, cancelError) {
10092
+ function syncTreeRemoveEventRegistration(syncTree, query, eventRegistration, cancelError, skipListenerDedup) {
10093
+ if (skipListenerDedup === void 0) { skipListenerDedup = false; }
10091
10094
  // Find the syncPoint first. Then deal with whether or not it has matching listeners
10092
10095
  var path = query._path;
10093
10096
  var maybeSyncPoint = syncTree.syncPointTree_.get(path);
@@ -10104,50 +10107,54 @@ function syncTreeRemoveEventRegistration(syncTree, query, eventRegistration, can
10104
10107
  }
10105
10108
  var removed = removedAndEvents.removed;
10106
10109
  cancelEvents = removedAndEvents.events;
10107
- // We may have just removed one of many listeners and can short-circuit this whole process
10108
- // We may also not have removed a default listener, in which case all of the descendant listeners should already be
10109
- // properly set up.
10110
- //
10111
- // Since indexed queries can shadow if they don't have other query constraints, check for loadsAllData(), instead of
10112
- // queryId === 'default'
10113
- var removingDefault = -1 !==
10114
- removed.findIndex(function (query) {
10115
- return query._queryParams.loadsAllData();
10110
+ if (!skipListenerDedup) {
10111
+ /**
10112
+ * We may have just removed one of many listeners and can short-circuit this whole process
10113
+ * We may also not have removed a default listener, in which case all of the descendant listeners should already be
10114
+ * properly set up.
10115
+ */
10116
+ // Since indexed queries can shadow if they don't have other query constraints, check for loadsAllData(), instead of
10117
+ // queryId === 'default'
10118
+ var removingDefault = -1 !==
10119
+ removed.findIndex(function (query) {
10120
+ return query._queryParams.loadsAllData();
10121
+ });
10122
+ var covered = syncTree.syncPointTree_.findOnPath(path, function (relativePath, parentSyncPoint) {
10123
+ return syncPointHasCompleteView(parentSyncPoint);
10116
10124
  });
10117
- var covered = syncTree.syncPointTree_.findOnPath(path, function (relativePath, parentSyncPoint) {
10118
- return syncPointHasCompleteView(parentSyncPoint);
10119
- });
10120
- if (removingDefault && !covered) {
10121
- var subtree = syncTree.syncPointTree_.subtree(path);
10122
- // There are potentially child listeners. Determine what if any listens we need to send before executing the
10123
- // removal
10124
- if (!subtree.isEmpty()) {
10125
- // We need to fold over our subtree and collect the listeners to send
10126
- var newViews = syncTreeCollectDistinctViewsForSubTree_(subtree);
10127
- // Ok, we've collected all the listens we need. Set them up.
10128
- for (var i = 0; i < newViews.length; ++i) {
10129
- var view = newViews[i], newQuery = view.query;
10130
- var listener = syncTreeCreateListenerForView_(syncTree, view);
10131
- syncTree.listenProvider_.startListening(syncTreeQueryForListening_(newQuery), syncTreeTagForQuery_(syncTree, newQuery), listener.hashFn, listener.onComplete);
10125
+ if (removingDefault && !covered) {
10126
+ var subtree = syncTree.syncPointTree_.subtree(path);
10127
+ // There are potentially child listeners. Determine what if any listens we need to send before executing the
10128
+ // removal
10129
+ if (!subtree.isEmpty()) {
10130
+ // We need to fold over our subtree and collect the listeners to send
10131
+ var newViews = syncTreeCollectDistinctViewsForSubTree_(subtree);
10132
+ // Ok, we've collected all the listens we need. Set them up.
10133
+ for (var i = 0; i < newViews.length; ++i) {
10134
+ var view = newViews[i], newQuery = view.query;
10135
+ var listener = syncTreeCreateListenerForView_(syncTree, view);
10136
+ syncTree.listenProvider_.startListening(syncTreeQueryForListening_(newQuery), syncTreeTagForQuery(syncTree, newQuery), listener.hashFn, listener.onComplete);
10137
+ }
10138
+ }
10139
+ // Otherwise there's nothing below us, so nothing we need to start listening on
10140
+ }
10141
+ // If we removed anything and we're not covered by a higher up listen, we need to stop listening on this query
10142
+ // The above block has us covered in terms of making sure we're set up on listens lower in the tree.
10143
+ // Also, note that if we have a cancelError, it's already been removed at the provider level.
10144
+ if (!covered && removed.length > 0 && !cancelError) {
10145
+ // If we removed a default, then we weren't listening on any of the other queries here. Just cancel the one
10146
+ // default. Otherwise, we need to iterate through and cancel each individual query
10147
+ if (removingDefault) {
10148
+ // We don't tag default listeners
10149
+ var defaultTag = null;
10150
+ syncTree.listenProvider_.stopListening(syncTreeQueryForListening_(query), defaultTag);
10151
+ }
10152
+ else {
10153
+ removed.forEach(function (queryToRemove) {
10154
+ var tagToRemove = syncTree.queryToTagMap.get(syncTreeMakeQueryKey_(queryToRemove));
10155
+ syncTree.listenProvider_.stopListening(syncTreeQueryForListening_(queryToRemove), tagToRemove);
10156
+ });
10132
10157
  }
10133
- }
10134
- }
10135
- // If we removed anything and we're not covered by a higher up listen, we need to stop listening on this query
10136
- // The above block has us covered in terms of making sure we're set up on listens lower in the tree.
10137
- // Also, note that if we have a cancelError, it's already been removed at the provider level.
10138
- if (!covered && removed.length > 0 && !cancelError) {
10139
- // If we removed a default, then we weren't listening on any of the other queries here. Just cancel the one
10140
- // default. Otherwise, we need to iterate through and cancel each individual query
10141
- if (removingDefault) {
10142
- // We don't tag default listeners
10143
- var defaultTag = null;
10144
- syncTree.listenProvider_.stopListening(syncTreeQueryForListening_(query), defaultTag);
10145
- }
10146
- else {
10147
- removed.forEach(function (queryToRemove) {
10148
- var tagToRemove = syncTree.queryToTagMap.get(syncTreeMakeQueryKey_(queryToRemove));
10149
- syncTree.listenProvider_.stopListening(syncTreeQueryForListening_(queryToRemove), tagToRemove);
10150
- });
10151
10158
  }
10152
10159
  }
10153
10160
  // Now, clear all of the tags we're tracking for the removed listens
@@ -10155,30 +10162,6 @@ function syncTreeRemoveEventRegistration(syncTree, query, eventRegistration, can
10155
10162
  }
10156
10163
  return cancelEvents;
10157
10164
  }
10158
- /**
10159
- * This function was added to support non-listener queries,
10160
- * specifically for use in repoGetValue. It sets up all the same
10161
- * local cache data-structures (SyncPoint + View) that are
10162
- * needed for listeners without installing an event registration.
10163
- * If `query` is not `loadsAllData`, it will also provision a tag for
10164
- * the query so that query results can be merged into the sync
10165
- * tree using existing logic for tagged listener queries.
10166
- *
10167
- * @param syncTree - Synctree to add the query to.
10168
- * @param query - Query to register
10169
- * @returns tag as a string if query is not a default query, null if query is not.
10170
- */
10171
- function syncTreeRegisterQuery(syncTree, query) {
10172
- var _a = syncTreeRegisterSyncPoint(query, syncTree), syncPoint = _a.syncPoint, serverCache = _a.serverCache, writesCache = _a.writesCache, serverCacheComplete = _a.serverCacheComplete;
10173
- var view = syncPointGetView(syncPoint, query, writesCache, serverCache, serverCacheComplete);
10174
- if (!syncPoint.views.has(query._queryIdentifier)) {
10175
- syncPoint.views.set(query._queryIdentifier, view);
10176
- }
10177
- if (!query._queryParams.loadsAllData()) {
10178
- return syncTreeTagForQuery_(syncTree, query);
10179
- }
10180
- return null;
10181
- }
10182
10165
  /**
10183
10166
  * Apply new server data for the specified tagged query.
10184
10167
  *
@@ -10219,11 +10202,12 @@ function syncTreeApplyTaggedQueryMerge(syncTree, path, changedChildren, tag) {
10219
10202
  }
10220
10203
  }
10221
10204
  /**
10222
- * Creates a new syncpoint for a query and creates a tag if the view doesn't exist.
10223
- * Extracted from addEventRegistration to allow `repoGetValue` to properly set up the SyncTree
10224
- * without actually listening on a query.
10205
+ * Add an event callback for the specified query.
10206
+ *
10207
+ * @returns Events to raise.
10225
10208
  */
10226
- function syncTreeRegisterSyncPoint(query, syncTree) {
10209
+ function syncTreeAddEventRegistration(syncTree, query, eventRegistration, skipSetupListener) {
10210
+ if (skipSetupListener === void 0) { skipSetupListener = false; }
10227
10211
  var path = query._path;
10228
10212
  var serverCache = null;
10229
10213
  var foundAncestorDefaultView = false;
@@ -10272,24 +10256,8 @@ function syncTreeRegisterSyncPoint(query, syncTree) {
10272
10256
  syncTree.tagToQueryMap.set(tag, queryKey);
10273
10257
  }
10274
10258
  var writesCache = writeTreeChildWrites(syncTree.pendingWriteTree_, path);
10275
- return {
10276
- syncPoint: syncPoint,
10277
- writesCache: writesCache,
10278
- serverCache: serverCache,
10279
- serverCacheComplete: serverCacheComplete,
10280
- foundAncestorDefaultView: foundAncestorDefaultView,
10281
- viewAlreadyExists: viewAlreadyExists
10282
- };
10283
- }
10284
- /**
10285
- * Add an event callback for the specified query.
10286
- *
10287
- * @returns Events to raise.
10288
- */
10289
- function syncTreeAddEventRegistration(syncTree, query, eventRegistration) {
10290
- var _a = syncTreeRegisterSyncPoint(query, syncTree), syncPoint = _a.syncPoint, serverCache = _a.serverCache, writesCache = _a.writesCache, serverCacheComplete = _a.serverCacheComplete, viewAlreadyExists = _a.viewAlreadyExists, foundAncestorDefaultView = _a.foundAncestorDefaultView;
10291
10259
  var events = syncPointAddEventRegistration(syncPoint, query, eventRegistration, writesCache, serverCache, serverCacheComplete);
10292
- if (!viewAlreadyExists && !foundAncestorDefaultView) {
10260
+ if (!viewAlreadyExists && !foundAncestorDefaultView && !skipSetupListener) {
10293
10261
  var view = syncPointViewForQuery(syncPoint, query);
10294
10262
  events = events.concat(syncTreeSetupListener_(syncTree, query, view));
10295
10263
  }
@@ -10419,7 +10387,7 @@ function syncTreeApplyOperationDescendantsHelper_(operation, syncPointTree, serv
10419
10387
  }
10420
10388
  function syncTreeCreateListenerForView_(syncTree, view) {
10421
10389
  var query = view.query;
10422
- var tag = syncTreeTagForQuery_(syncTree, query);
10390
+ var tag = syncTreeTagForQuery(syncTree, query);
10423
10391
  return {
10424
10392
  hashFn: function () {
10425
10393
  var cache = viewGetServerCache(view) || ChildrenNode.EMPTY_NODE;
@@ -10447,7 +10415,7 @@ function syncTreeCreateListenerForView_(syncTree, view) {
10447
10415
  /**
10448
10416
  * Return the tag associated with the given query.
10449
10417
  */
10450
- function syncTreeTagForQuery_(syncTree, query) {
10418
+ function syncTreeTagForQuery(syncTree, query) {
10451
10419
  var queryKey = syncTreeMakeQueryKey_(query);
10452
10420
  return syncTree.queryToTagMap.get(queryKey);
10453
10421
  }
@@ -10547,7 +10515,7 @@ function syncTreeGetNextQueryTag_() {
10547
10515
  */
10548
10516
  function syncTreeSetupListener_(syncTree, query, view) {
10549
10517
  var path = query._path;
10550
- var tag = syncTreeTagForQuery_(syncTree, query);
10518
+ var tag = syncTreeTagForQuery(syncTree, query);
10551
10519
  var listener = syncTreeCreateListenerForView_(syncTree, view);
10552
10520
  var events = syncTree.listenProvider_.startListening(syncTreeQueryForListening_(query), tag, listener.hashFn, listener.onComplete);
10553
10521
  var subtree = syncTree.syncPointTree_.subtree(path);
@@ -10578,7 +10546,7 @@ function syncTreeSetupListener_(syncTree, query, view) {
10578
10546
  });
10579
10547
  for (var i = 0; i < queriesToStop.length; ++i) {
10580
10548
  var queryToStop = queriesToStop[i];
10581
- syncTree.listenProvider_.stopListening(syncTreeQueryForListening_(queryToStop), syncTreeTagForQuery_(syncTree, queryToStop));
10549
+ syncTree.listenProvider_.stopListening(syncTreeQueryForListening_(queryToStop), syncTreeTagForQuery(syncTree, queryToStop));
10582
10550
  }
10583
10551
  }
10584
10552
  return events;
@@ -11515,14 +11483,14 @@ function repoGetNextWriteId(repo) {
11515
11483
  * belonging to active listeners. If they are found, such values
11516
11484
  * are considered to be the most up-to-date.
11517
11485
  *
11518
- * If the client is not connected, this method will try to
11519
- * establish a connection and request the value for `query`. If
11520
- * the client is not able to retrieve the query result, it reports
11521
- * an error.
11486
+ * If the client is not connected, this method will wait until the
11487
+ * repo has established a connection and then request the value for `query`.
11488
+ * If the client is not able to retrieve the query result for another reason,
11489
+ * it reports an error.
11522
11490
  *
11523
11491
  * @param query - The query to surface a value for.
11524
11492
  */
11525
- function repoGetValue(repo, query) {
11493
+ function repoGetValue(repo, query, eventRegistration) {
11526
11494
  // Only active queries are cached. There is no persisted cache.
11527
11495
  var cached = syncTreeGetServerValue(repo.serverSyncTree_, query);
11528
11496
  if (cached != null) {
@@ -11530,24 +11498,34 @@ function repoGetValue(repo, query) {
11530
11498
  }
11531
11499
  return repo.server_.get(query).then(function (payload) {
11532
11500
  var node = nodeFromJSON(payload).withIndex(query._queryParams.getIndex());
11533
- // if this is a filtered query, then overwrite at path
11501
+ /**
11502
+ * Below we simulate the actions of an `onlyOnce` `onValue()` event where:
11503
+ * Add an event registration,
11504
+ * Update data at the path,
11505
+ * Raise any events,
11506
+ * Cleanup the SyncTree
11507
+ */
11508
+ syncTreeAddEventRegistration(repo.serverSyncTree_, query, eventRegistration, true);
11509
+ var events;
11534
11510
  if (query._queryParams.loadsAllData()) {
11535
- syncTreeApplyServerOverwrite(repo.serverSyncTree_, query._path, node);
11511
+ events = syncTreeApplyServerOverwrite(repo.serverSyncTree_, query._path, node);
11536
11512
  }
11537
11513
  else {
11538
- // Simulate `syncTreeAddEventRegistration` without events/listener setup.
11539
- // We do this (along with the syncTreeRemoveEventRegistration` below) so that
11540
- // `repoGetValue` results have the same cache effects as initial listener(s)
11541
- // updates.
11542
- var tag = syncTreeRegisterQuery(repo.serverSyncTree_, query);
11543
- syncTreeApplyTaggedQueryOverwrite(repo.serverSyncTree_, query._path, node, tag);
11544
- // Call `syncTreeRemoveEventRegistration` with a null event registration, since there is none.
11545
- // Note: The below code essentially unregisters the query and cleans up any views/syncpoints temporarily created above.
11546
- }
11547
- var cancels = syncTreeRemoveEventRegistration(repo.serverSyncTree_, query, null);
11548
- if (cancels.length > 0) {
11549
- repoLog(repo, 'unexpected cancel events in repoGetValue');
11514
+ var tag = syncTreeTagForQuery(repo.serverSyncTree_, query);
11515
+ events = syncTreeApplyTaggedQueryOverwrite(repo.serverSyncTree_, query._path, node, tag);
11550
11516
  }
11517
+ /*
11518
+ * We need to raise events in the scenario where `get()` is called at a parent path, and
11519
+ * while the `get()` is pending, `onValue` is called at a child location. While get() is waiting
11520
+ * for the data, `onValue` will register a new event. Then, get() will come back, and update the syncTree
11521
+ * and its corresponding serverCache, including the child location where `onValue` is called. Then,
11522
+ * `onValue` will receive the event from the server, but look at the syncTree and see that the data received
11523
+ * from the server is already at the SyncPoint, and so the `onValue` callback will never get fired.
11524
+ * Calling `eventQueueRaiseEventsForChangedPath()` is the correct way to propagate the events and
11525
+ * ensure the corresponding child events will get fired.
11526
+ */
11527
+ eventQueueRaiseEventsForChangedPath(repo.eventQueue_, query._path, events);
11528
+ syncTreeRemoveEventRegistration(repo.serverSyncTree_, query, eventRegistration, null, true);
11551
11529
  return node;
11552
11530
  }, function (err) {
11553
11531
  repoLog(repo, 'get for query ' + stringify(query) + ' failed: ' + err);
@@ -13307,7 +13285,9 @@ function update(ref, values) {
13307
13285
  */
13308
13286
  function get(query) {
13309
13287
  query = getModularInstance(query);
13310
- return repoGetValue(query._repo, query).then(function (node) {
13288
+ var callbackContext = new CallbackContext(function () { });
13289
+ var container = new ValueEventRegistration(callbackContext);
13290
+ return repoGetValue(query._repo, query, container).then(function (node) {
13311
13291
  return new DataSnapshot(node, new ReferenceImpl(query._repo, query._path), query._queryParams.getIndex());
13312
13292
  });
13313
13293
  }