@firebase/database 0.13.4-canary.ac578e98f → 0.13.4-canary.dcfebe8dc
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.
- package/dist/index.esm2017.js +91 -113
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm5.js +94 -114
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +94 -114
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/index.standalone.js +93 -113
- package/dist/index.standalone.js.map +1 -1
- package/dist/internal.d.ts +1 -3
- package/dist/node-esm/index.node.esm.js +91 -113
- package/dist/node-esm/index.node.esm.js.map +1 -1
- package/dist/node-esm/src/api/Reference_impl.d.ts +1 -3
- package/dist/node-esm/src/core/Repo.d.ts +6 -5
- package/dist/node-esm/src/core/SyncTree.d.ts +9 -30
- package/dist/node-esm/test/helpers/util.d.ts +10 -4
- package/dist/private.d.ts +1 -3
- package/dist/public.d.ts +1 -3
- package/dist/src/api/Reference_impl.d.ts +1 -3
- package/dist/src/core/Repo.d.ts +6 -5
- package/dist/src/core/SyncTree.d.ts +9 -30
- package/dist/test/helpers/util.d.ts +10 -4
- package/package.json +6 -6
package/dist/internal.d.ts
CHANGED
|
@@ -338,9 +338,7 @@ export declare class DataSnapshot {
|
|
|
338
338
|
* @returns true if enumeration was canceled due to your callback returning
|
|
339
339
|
* true.
|
|
340
340
|
*/
|
|
341
|
-
forEach(action: (child: DataSnapshot
|
|
342
|
-
key: string;
|
|
343
|
-
}) => boolean | void): boolean;
|
|
341
|
+
forEach(action: (child: DataSnapshot) => boolean | void): boolean;
|
|
344
342
|
/**
|
|
345
343
|
* Returns true if the specified child path has (non-null) data.
|
|
346
344
|
*
|
|
@@ -1241,7 +1241,7 @@ WebSocketConnection.responsesRequiredToBeHealthy = 2;
|
|
|
1241
1241
|
WebSocketConnection.healthyTimeout = 30000;
|
|
1242
1242
|
|
|
1243
1243
|
const name = "@firebase/database";
|
|
1244
|
-
const version = "0.13.4-canary.
|
|
1244
|
+
const version = "0.13.4-canary.dcfebe8dc";
|
|
1245
1245
|
|
|
1246
1246
|
/**
|
|
1247
1247
|
* @license
|
|
@@ -9139,7 +9139,7 @@ function viewProcessorApplyServerMerge(viewProcessor, viewCache, path, changedCh
|
|
|
9139
9139
|
});
|
|
9140
9140
|
viewMergeTree.children.inorderTraversal((childKey, childMergeTree) => {
|
|
9141
9141
|
const isUnknownDeepMerge = !viewCache.serverCache.isCompleteForChild(childKey) &&
|
|
9142
|
-
childMergeTree.value ===
|
|
9142
|
+
childMergeTree.value === null;
|
|
9143
9143
|
if (!serverNode.hasChild(childKey) && !isUnknownDeepMerge) {
|
|
9144
9144
|
const serverChild = viewCache.serverCache
|
|
9145
9145
|
.getNode()
|
|
@@ -9778,9 +9778,11 @@ function syncTreeApplyTaggedListenComplete(syncTree, path, tag) {
|
|
|
9778
9778
|
*
|
|
9779
9779
|
* @param eventRegistration - If null, all callbacks are removed.
|
|
9780
9780
|
* @param cancelError - If a cancelError is provided, appropriate cancel events will be returned.
|
|
9781
|
+
* @param skipListenerDedup - When performing a `get()`, we don't add any new listeners, so no
|
|
9782
|
+
* deduping needs to take place. This flag allows toggling of that behavior
|
|
9781
9783
|
* @returns Cancel events, if cancelError was provided.
|
|
9782
9784
|
*/
|
|
9783
|
-
function syncTreeRemoveEventRegistration(syncTree, query, eventRegistration, cancelError) {
|
|
9785
|
+
function syncTreeRemoveEventRegistration(syncTree, query, eventRegistration, cancelError, skipListenerDedup = false) {
|
|
9784
9786
|
// Find the syncPoint first. Then deal with whether or not it has matching listeners
|
|
9785
9787
|
const path = query._path;
|
|
9786
9788
|
const maybeSyncPoint = syncTree.syncPointTree_.get(path);
|
|
@@ -9797,48 +9799,52 @@ function syncTreeRemoveEventRegistration(syncTree, query, eventRegistration, can
|
|
|
9797
9799
|
}
|
|
9798
9800
|
const removed = removedAndEvents.removed;
|
|
9799
9801
|
cancelEvents = removedAndEvents.events;
|
|
9800
|
-
|
|
9801
|
-
|
|
9802
|
-
|
|
9803
|
-
|
|
9804
|
-
|
|
9805
|
-
|
|
9806
|
-
|
|
9807
|
-
|
|
9808
|
-
|
|
9809
|
-
|
|
9810
|
-
|
|
9811
|
-
if (removingDefault && !covered) {
|
|
9812
|
-
const subtree = syncTree.syncPointTree_.subtree(path);
|
|
9813
|
-
// There are potentially child listeners. Determine what if any listens we need to send before executing the
|
|
9814
|
-
// removal
|
|
9815
|
-
if (!subtree.isEmpty()) {
|
|
9816
|
-
// We need to fold over our subtree and collect the listeners to send
|
|
9817
|
-
const newViews = syncTreeCollectDistinctViewsForSubTree_(subtree);
|
|
9818
|
-
// Ok, we've collected all the listens we need. Set them up.
|
|
9819
|
-
for (let i = 0; i < newViews.length; ++i) {
|
|
9820
|
-
const view = newViews[i], newQuery = view.query;
|
|
9821
|
-
const listener = syncTreeCreateListenerForView_(syncTree, view);
|
|
9822
|
-
syncTree.listenProvider_.startListening(syncTreeQueryForListening_(newQuery), syncTreeTagForQuery_(syncTree, newQuery), listener.hashFn, listener.onComplete);
|
|
9823
|
-
}
|
|
9824
|
-
}
|
|
9825
|
-
}
|
|
9826
|
-
// If we removed anything and we're not covered by a higher up listen, we need to stop listening on this query
|
|
9827
|
-
// The above block has us covered in terms of making sure we're set up on listens lower in the tree.
|
|
9828
|
-
// Also, note that if we have a cancelError, it's already been removed at the provider level.
|
|
9829
|
-
if (!covered && removed.length > 0 && !cancelError) {
|
|
9830
|
-
// If we removed a default, then we weren't listening on any of the other queries here. Just cancel the one
|
|
9831
|
-
// default. Otherwise, we need to iterate through and cancel each individual query
|
|
9832
|
-
if (removingDefault) {
|
|
9833
|
-
// We don't tag default listeners
|
|
9834
|
-
const defaultTag = null;
|
|
9835
|
-
syncTree.listenProvider_.stopListening(syncTreeQueryForListening_(query), defaultTag);
|
|
9836
|
-
}
|
|
9837
|
-
else {
|
|
9838
|
-
removed.forEach((queryToRemove) => {
|
|
9839
|
-
const tagToRemove = syncTree.queryToTagMap.get(syncTreeMakeQueryKey_(queryToRemove));
|
|
9840
|
-
syncTree.listenProvider_.stopListening(syncTreeQueryForListening_(queryToRemove), tagToRemove);
|
|
9802
|
+
if (!skipListenerDedup) {
|
|
9803
|
+
/**
|
|
9804
|
+
* We may have just removed one of many listeners and can short-circuit this whole process
|
|
9805
|
+
* We may also not have removed a default listener, in which case all of the descendant listeners should already be
|
|
9806
|
+
* properly set up.
|
|
9807
|
+
*/
|
|
9808
|
+
// Since indexed queries can shadow if they don't have other query constraints, check for loadsAllData(), instead of
|
|
9809
|
+
// queryId === 'default'
|
|
9810
|
+
const removingDefault = -1 !==
|
|
9811
|
+
removed.findIndex(query => {
|
|
9812
|
+
return query._queryParams.loadsAllData();
|
|
9841
9813
|
});
|
|
9814
|
+
const covered = syncTree.syncPointTree_.findOnPath(path, (relativePath, parentSyncPoint) => syncPointHasCompleteView(parentSyncPoint));
|
|
9815
|
+
if (removingDefault && !covered) {
|
|
9816
|
+
const subtree = syncTree.syncPointTree_.subtree(path);
|
|
9817
|
+
// There are potentially child listeners. Determine what if any listens we need to send before executing the
|
|
9818
|
+
// removal
|
|
9819
|
+
if (!subtree.isEmpty()) {
|
|
9820
|
+
// We need to fold over our subtree and collect the listeners to send
|
|
9821
|
+
const newViews = syncTreeCollectDistinctViewsForSubTree_(subtree);
|
|
9822
|
+
// Ok, we've collected all the listens we need. Set them up.
|
|
9823
|
+
for (let i = 0; i < newViews.length; ++i) {
|
|
9824
|
+
const view = newViews[i], newQuery = view.query;
|
|
9825
|
+
const listener = syncTreeCreateListenerForView_(syncTree, view);
|
|
9826
|
+
syncTree.listenProvider_.startListening(syncTreeQueryForListening_(newQuery), syncTreeTagForQuery(syncTree, newQuery), listener.hashFn, listener.onComplete);
|
|
9827
|
+
}
|
|
9828
|
+
}
|
|
9829
|
+
// Otherwise there's nothing below us, so nothing we need to start listening on
|
|
9830
|
+
}
|
|
9831
|
+
// If we removed anything and we're not covered by a higher up listen, we need to stop listening on this query
|
|
9832
|
+
// The above block has us covered in terms of making sure we're set up on listens lower in the tree.
|
|
9833
|
+
// Also, note that if we have a cancelError, it's already been removed at the provider level.
|
|
9834
|
+
if (!covered && removed.length > 0 && !cancelError) {
|
|
9835
|
+
// If we removed a default, then we weren't listening on any of the other queries here. Just cancel the one
|
|
9836
|
+
// default. Otherwise, we need to iterate through and cancel each individual query
|
|
9837
|
+
if (removingDefault) {
|
|
9838
|
+
// We don't tag default listeners
|
|
9839
|
+
const defaultTag = null;
|
|
9840
|
+
syncTree.listenProvider_.stopListening(syncTreeQueryForListening_(query), defaultTag);
|
|
9841
|
+
}
|
|
9842
|
+
else {
|
|
9843
|
+
removed.forEach((queryToRemove) => {
|
|
9844
|
+
const tagToRemove = syncTree.queryToTagMap.get(syncTreeMakeQueryKey_(queryToRemove));
|
|
9845
|
+
syncTree.listenProvider_.stopListening(syncTreeQueryForListening_(queryToRemove), tagToRemove);
|
|
9846
|
+
});
|
|
9847
|
+
}
|
|
9842
9848
|
}
|
|
9843
9849
|
}
|
|
9844
9850
|
// Now, clear all of the tags we're tracking for the removed listens
|
|
@@ -9846,30 +9852,6 @@ function syncTreeRemoveEventRegistration(syncTree, query, eventRegistration, can
|
|
|
9846
9852
|
}
|
|
9847
9853
|
return cancelEvents;
|
|
9848
9854
|
}
|
|
9849
|
-
/**
|
|
9850
|
-
* This function was added to support non-listener queries,
|
|
9851
|
-
* specifically for use in repoGetValue. It sets up all the same
|
|
9852
|
-
* local cache data-structures (SyncPoint + View) that are
|
|
9853
|
-
* needed for listeners without installing an event registration.
|
|
9854
|
-
* If `query` is not `loadsAllData`, it will also provision a tag for
|
|
9855
|
-
* the query so that query results can be merged into the sync
|
|
9856
|
-
* tree using existing logic for tagged listener queries.
|
|
9857
|
-
*
|
|
9858
|
-
* @param syncTree - Synctree to add the query to.
|
|
9859
|
-
* @param query - Query to register
|
|
9860
|
-
* @returns tag as a string if query is not a default query, null if query is not.
|
|
9861
|
-
*/
|
|
9862
|
-
function syncTreeRegisterQuery(syncTree, query) {
|
|
9863
|
-
const { syncPoint, serverCache, writesCache, serverCacheComplete } = syncTreeRegisterSyncPoint(query, syncTree);
|
|
9864
|
-
const view = syncPointGetView(syncPoint, query, writesCache, serverCache, serverCacheComplete);
|
|
9865
|
-
if (!syncPoint.views.has(query._queryIdentifier)) {
|
|
9866
|
-
syncPoint.views.set(query._queryIdentifier, view);
|
|
9867
|
-
}
|
|
9868
|
-
if (!query._queryParams.loadsAllData()) {
|
|
9869
|
-
return syncTreeTagForQuery_(syncTree, query);
|
|
9870
|
-
}
|
|
9871
|
-
return null;
|
|
9872
|
-
}
|
|
9873
9855
|
/**
|
|
9874
9856
|
* Apply new server data for the specified tagged query.
|
|
9875
9857
|
*
|
|
@@ -9910,11 +9892,11 @@ function syncTreeApplyTaggedQueryMerge(syncTree, path, changedChildren, tag) {
|
|
|
9910
9892
|
}
|
|
9911
9893
|
}
|
|
9912
9894
|
/**
|
|
9913
|
-
*
|
|
9914
|
-
*
|
|
9915
|
-
*
|
|
9895
|
+
* Add an event callback for the specified query.
|
|
9896
|
+
*
|
|
9897
|
+
* @returns Events to raise.
|
|
9916
9898
|
*/
|
|
9917
|
-
function
|
|
9899
|
+
function syncTreeAddEventRegistration(syncTree, query, eventRegistration, skipSetupListener = false) {
|
|
9918
9900
|
const path = query._path;
|
|
9919
9901
|
let serverCache = null;
|
|
9920
9902
|
let foundAncestorDefaultView = false;
|
|
@@ -9963,24 +9945,8 @@ function syncTreeRegisterSyncPoint(query, syncTree) {
|
|
|
9963
9945
|
syncTree.tagToQueryMap.set(tag, queryKey);
|
|
9964
9946
|
}
|
|
9965
9947
|
const writesCache = writeTreeChildWrites(syncTree.pendingWriteTree_, path);
|
|
9966
|
-
return {
|
|
9967
|
-
syncPoint,
|
|
9968
|
-
writesCache,
|
|
9969
|
-
serverCache,
|
|
9970
|
-
serverCacheComplete,
|
|
9971
|
-
foundAncestorDefaultView,
|
|
9972
|
-
viewAlreadyExists
|
|
9973
|
-
};
|
|
9974
|
-
}
|
|
9975
|
-
/**
|
|
9976
|
-
* Add an event callback for the specified query.
|
|
9977
|
-
*
|
|
9978
|
-
* @returns Events to raise.
|
|
9979
|
-
*/
|
|
9980
|
-
function syncTreeAddEventRegistration(syncTree, query, eventRegistration) {
|
|
9981
|
-
const { syncPoint, serverCache, writesCache, serverCacheComplete, viewAlreadyExists, foundAncestorDefaultView } = syncTreeRegisterSyncPoint(query, syncTree);
|
|
9982
9948
|
let events = syncPointAddEventRegistration(syncPoint, query, eventRegistration, writesCache, serverCache, serverCacheComplete);
|
|
9983
|
-
if (!viewAlreadyExists && !foundAncestorDefaultView) {
|
|
9949
|
+
if (!viewAlreadyExists && !foundAncestorDefaultView && !skipSetupListener) {
|
|
9984
9950
|
const view = syncPointViewForQuery(syncPoint, query);
|
|
9985
9951
|
events = events.concat(syncTreeSetupListener_(syncTree, query, view));
|
|
9986
9952
|
}
|
|
@@ -10110,7 +10076,7 @@ function syncTreeApplyOperationDescendantsHelper_(operation, syncPointTree, serv
|
|
|
10110
10076
|
}
|
|
10111
10077
|
function syncTreeCreateListenerForView_(syncTree, view) {
|
|
10112
10078
|
const query = view.query;
|
|
10113
|
-
const tag =
|
|
10079
|
+
const tag = syncTreeTagForQuery(syncTree, query);
|
|
10114
10080
|
return {
|
|
10115
10081
|
hashFn: () => {
|
|
10116
10082
|
const cache = viewGetServerCache(view) || ChildrenNode.EMPTY_NODE;
|
|
@@ -10138,7 +10104,7 @@ function syncTreeCreateListenerForView_(syncTree, view) {
|
|
|
10138
10104
|
/**
|
|
10139
10105
|
* Return the tag associated with the given query.
|
|
10140
10106
|
*/
|
|
10141
|
-
function
|
|
10107
|
+
function syncTreeTagForQuery(syncTree, query) {
|
|
10142
10108
|
const queryKey = syncTreeMakeQueryKey_(query);
|
|
10143
10109
|
return syncTree.queryToTagMap.get(queryKey);
|
|
10144
10110
|
}
|
|
@@ -10238,7 +10204,7 @@ function syncTreeGetNextQueryTag_() {
|
|
|
10238
10204
|
*/
|
|
10239
10205
|
function syncTreeSetupListener_(syncTree, query, view) {
|
|
10240
10206
|
const path = query._path;
|
|
10241
|
-
const tag =
|
|
10207
|
+
const tag = syncTreeTagForQuery(syncTree, query);
|
|
10242
10208
|
const listener = syncTreeCreateListenerForView_(syncTree, view);
|
|
10243
10209
|
const events = syncTree.listenProvider_.startListening(syncTreeQueryForListening_(query), tag, listener.hashFn, listener.onComplete);
|
|
10244
10210
|
const subtree = syncTree.syncPointTree_.subtree(path);
|
|
@@ -10269,7 +10235,7 @@ function syncTreeSetupListener_(syncTree, query, view) {
|
|
|
10269
10235
|
});
|
|
10270
10236
|
for (let i = 0; i < queriesToStop.length; ++i) {
|
|
10271
10237
|
const queryToStop = queriesToStop[i];
|
|
10272
|
-
syncTree.listenProvider_.stopListening(syncTreeQueryForListening_(queryToStop),
|
|
10238
|
+
syncTree.listenProvider_.stopListening(syncTreeQueryForListening_(queryToStop), syncTreeTagForQuery(syncTree, queryToStop));
|
|
10273
10239
|
}
|
|
10274
10240
|
}
|
|
10275
10241
|
return events;
|
|
@@ -11194,14 +11160,14 @@ function repoGetNextWriteId(repo) {
|
|
|
11194
11160
|
* belonging to active listeners. If they are found, such values
|
|
11195
11161
|
* are considered to be the most up-to-date.
|
|
11196
11162
|
*
|
|
11197
|
-
* If the client is not connected, this method will
|
|
11198
|
-
*
|
|
11199
|
-
* the client is not able to retrieve the query result
|
|
11200
|
-
* an error.
|
|
11163
|
+
* If the client is not connected, this method will wait until the
|
|
11164
|
+
* repo has established a connection and then request the value for `query`.
|
|
11165
|
+
* If the client is not able to retrieve the query result for another reason,
|
|
11166
|
+
* it reports an error.
|
|
11201
11167
|
*
|
|
11202
11168
|
* @param query - The query to surface a value for.
|
|
11203
11169
|
*/
|
|
11204
|
-
function repoGetValue(repo, query) {
|
|
11170
|
+
function repoGetValue(repo, query, eventRegistration) {
|
|
11205
11171
|
// Only active queries are cached. There is no persisted cache.
|
|
11206
11172
|
const cached = syncTreeGetServerValue(repo.serverSyncTree_, query);
|
|
11207
11173
|
if (cached != null) {
|
|
@@ -11209,24 +11175,34 @@ function repoGetValue(repo, query) {
|
|
|
11209
11175
|
}
|
|
11210
11176
|
return repo.server_.get(query).then(payload => {
|
|
11211
11177
|
const node = nodeFromJSON(payload).withIndex(query._queryParams.getIndex());
|
|
11212
|
-
|
|
11178
|
+
/**
|
|
11179
|
+
* Below we simulate the actions of an `onlyOnce` `onValue()` event where:
|
|
11180
|
+
* Add an event registration,
|
|
11181
|
+
* Update data at the path,
|
|
11182
|
+
* Raise any events,
|
|
11183
|
+
* Cleanup the SyncTree
|
|
11184
|
+
*/
|
|
11185
|
+
syncTreeAddEventRegistration(repo.serverSyncTree_, query, eventRegistration, true);
|
|
11186
|
+
let events;
|
|
11213
11187
|
if (query._queryParams.loadsAllData()) {
|
|
11214
|
-
syncTreeApplyServerOverwrite(repo.serverSyncTree_, query._path, node);
|
|
11188
|
+
events = syncTreeApplyServerOverwrite(repo.serverSyncTree_, query._path, node);
|
|
11215
11189
|
}
|
|
11216
11190
|
else {
|
|
11217
|
-
|
|
11218
|
-
|
|
11219
|
-
// `repoGetValue` results have the same cache effects as initial listener(s)
|
|
11220
|
-
// updates.
|
|
11221
|
-
const tag = syncTreeRegisterQuery(repo.serverSyncTree_, query);
|
|
11222
|
-
syncTreeApplyTaggedQueryOverwrite(repo.serverSyncTree_, query._path, node, tag);
|
|
11223
|
-
// Call `syncTreeRemoveEventRegistration` with a null event registration, since there is none.
|
|
11224
|
-
// Note: The below code essentially unregisters the query and cleans up any views/syncpoints temporarily created above.
|
|
11225
|
-
}
|
|
11226
|
-
const cancels = syncTreeRemoveEventRegistration(repo.serverSyncTree_, query, null);
|
|
11227
|
-
if (cancels.length > 0) {
|
|
11228
|
-
repoLog(repo, 'unexpected cancel events in repoGetValue');
|
|
11191
|
+
const tag = syncTreeTagForQuery(repo.serverSyncTree_, query);
|
|
11192
|
+
events = syncTreeApplyTaggedQueryOverwrite(repo.serverSyncTree_, query._path, node, tag);
|
|
11229
11193
|
}
|
|
11194
|
+
/*
|
|
11195
|
+
* We need to raise events in the scenario where `get()` is called at a parent path, and
|
|
11196
|
+
* while the `get()` is pending, `onValue` is called at a child location. While get() is waiting
|
|
11197
|
+
* for the data, `onValue` will register a new event. Then, get() will come back, and update the syncTree
|
|
11198
|
+
* and its corresponding serverCache, including the child location where `onValue` is called. Then,
|
|
11199
|
+
* `onValue` will receive the event from the server, but look at the syncTree and see that the data received
|
|
11200
|
+
* from the server is already at the SyncPoint, and so the `onValue` callback will never get fired.
|
|
11201
|
+
* Calling `eventQueueRaiseEventsForChangedPath()` is the correct way to propagate the events and
|
|
11202
|
+
* ensure the corresponding child events will get fired.
|
|
11203
|
+
*/
|
|
11204
|
+
eventQueueRaiseEventsForChangedPath(repo.eventQueue_, query._path, events);
|
|
11205
|
+
syncTreeRemoveEventRegistration(repo.serverSyncTree_, query, eventRegistration, null, true);
|
|
11230
11206
|
return node;
|
|
11231
11207
|
}, err => {
|
|
11232
11208
|
repoLog(repo, 'get for query ' + stringify(query) + ' failed: ' + err);
|
|
@@ -12909,7 +12885,9 @@ function update(ref, values) {
|
|
|
12909
12885
|
*/
|
|
12910
12886
|
function get(query) {
|
|
12911
12887
|
query = getModularInstance(query);
|
|
12912
|
-
|
|
12888
|
+
const callbackContext = new CallbackContext(() => { });
|
|
12889
|
+
const container = new ValueEventRegistration(callbackContext);
|
|
12890
|
+
return repoGetValue(query._repo, query, container).then(node => {
|
|
12913
12891
|
return new DataSnapshot(node, new ReferenceImpl(query._repo, query._path), query._queryParams.getIndex());
|
|
12914
12892
|
});
|
|
12915
12893
|
}
|