@firebase/firestore 3.4.9 → 3.4.10-canary.8e952e2ee
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/CHANGELOG.md +14 -0
- package/dist/firestore/src/api/transaction.d.ts +2 -0
- package/dist/firestore/src/core/component_provider.d.ts +11 -6
- package/dist/firestore/src/lite-api/transaction.d.ts +2 -0
- package/dist/firestore/src/local/document_overlay_cache.d.ts +5 -0
- package/dist/firestore/src/local/index_backfiller.d.ts +44 -0
- package/dist/firestore/src/local/index_manager.d.ts +2 -0
- package/dist/firestore/src/local/indexeddb_document_overlay_cache.d.ts +1 -0
- package/dist/firestore/src/local/indexeddb_index_manager.d.ts +1 -0
- package/dist/firestore/src/local/indexeddb_schema.d.ts +3 -2
- package/dist/firestore/src/local/indexeddb_schema_converter.d.ts +1 -0
- package/dist/firestore/src/local/indexeddb_sentinels.d.ts +1 -0
- package/dist/firestore/src/local/local_documents_view.d.ts +64 -9
- package/dist/firestore/src/local/local_store.d.ts +9 -0
- package/dist/firestore/src/local/lru_garbage_collector_impl.d.ts +5 -5
- package/dist/firestore/src/local/memory_document_overlay_cache.d.ts +1 -0
- package/dist/firestore/src/local/memory_index_manager.d.ts +1 -0
- package/dist/firestore/src/local/overlayed_document.d.ts +36 -0
- package/dist/firestore/src/local/persistence.d.ts +3 -5
- package/dist/firestore/src/local/persistence_promise.d.ts +11 -0
- package/dist/firestore/src/local/query_engine.d.ts +1 -1
- package/dist/firestore/src/model/collections.d.ts +8 -2
- package/dist/firestore/src/model/field_mask.d.ts +6 -0
- package/dist/firestore/src/model/mutation.d.ts +19 -1
- package/dist/firestore/src/model/mutation_batch.d.ts +8 -4
- package/dist/firestore/src/tsdoc-metadata.json +11 -11
- package/dist/firestore/src/util/async_queue.d.ts +5 -1
- package/dist/firestore/test/unit/local/index_backfiller.test.d.ts +17 -0
- package/dist/firestore/test/unit/local/test_document_overlay_cache.d.ts +1 -0
- package/dist/firestore/test/unit/specs/spec_test_components.d.ts +5 -3
- package/dist/firestore/test/util/helpers.d.ts +13 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.esm2017.js +10698 -10303
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm5.js +10986 -10471
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +6349 -5731
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/index.node.mjs +6349 -5731
- package/dist/index.node.mjs.map +1 -1
- package/dist/index.rn.js +10687 -10291
- package/dist/index.rn.js.map +1 -1
- package/dist/internal.d.ts +6137 -5964
- package/dist/lite/firestore/src/api/transaction.d.ts +2 -0
- package/dist/lite/firestore/src/core/component_provider.d.ts +11 -6
- package/dist/lite/firestore/src/lite-api/transaction.d.ts +2 -0
- package/dist/lite/firestore/src/local/document_overlay_cache.d.ts +5 -0
- package/dist/lite/firestore/src/local/index_backfiller.d.ts +44 -0
- package/dist/lite/firestore/src/local/index_manager.d.ts +2 -0
- package/dist/lite/firestore/src/local/indexeddb_document_overlay_cache.d.ts +1 -0
- package/dist/lite/firestore/src/local/indexeddb_index_manager.d.ts +1 -0
- package/dist/lite/firestore/src/local/indexeddb_schema.d.ts +3 -2
- package/dist/lite/firestore/src/local/indexeddb_schema_converter.d.ts +1 -0
- package/dist/lite/firestore/src/local/indexeddb_sentinels.d.ts +1 -0
- package/dist/lite/firestore/src/local/local_documents_view.d.ts +64 -9
- package/dist/lite/firestore/src/local/local_store.d.ts +9 -0
- package/dist/lite/firestore/src/local/lru_garbage_collector_impl.d.ts +5 -5
- package/dist/lite/firestore/src/local/memory_document_overlay_cache.d.ts +1 -0
- package/dist/lite/firestore/src/local/memory_index_manager.d.ts +1 -0
- package/dist/lite/firestore/src/local/overlayed_document.d.ts +36 -0
- package/dist/lite/firestore/src/local/persistence.d.ts +3 -5
- package/dist/lite/firestore/src/local/persistence_promise.d.ts +11 -0
- package/dist/lite/firestore/src/local/query_engine.d.ts +1 -1
- package/dist/lite/firestore/src/model/collections.d.ts +8 -2
- package/dist/lite/firestore/src/model/field_mask.d.ts +6 -0
- package/dist/lite/firestore/src/model/mutation.d.ts +19 -1
- package/dist/lite/firestore/src/model/mutation_batch.d.ts +8 -4
- package/dist/lite/firestore/src/util/async_queue.d.ts +5 -1
- package/dist/lite/firestore/test/unit/local/index_backfiller.test.d.ts +17 -0
- package/dist/lite/firestore/test/unit/local/test_document_overlay_cache.d.ts +1 -0
- package/dist/lite/firestore/test/unit/specs/spec_test_components.d.ts +5 -3
- package/dist/lite/firestore/test/util/helpers.d.ts +13 -0
- package/dist/lite/index.browser.esm2017.js +1220 -738
- package/dist/lite/index.browser.esm2017.js.map +1 -1
- package/dist/lite/index.browser.esm5.js +1156 -764
- package/dist/lite/index.browser.esm5.js.map +1 -1
- package/dist/lite/index.d.ts +2 -0
- package/dist/lite/index.node.cjs.js +655 -2
- package/dist/lite/index.node.cjs.js.map +1 -1
- package/dist/lite/index.node.mjs +655 -2
- package/dist/lite/index.node.mjs.map +1 -1
- package/dist/lite/index.rn.esm2017.js +1184 -702
- package/dist/lite/index.rn.esm2017.js.map +1 -1
- package/dist/lite/internal.d.ts +2916 -2898
- package/dist/lite/packages/firestore/dist/lite/index.browser.esm2017.d.ts +106 -104
- package/dist/lite/packages/firestore/src/api/transaction.d.ts +2 -0
- package/dist/lite/packages/firestore/src/core/component_provider.d.ts +11 -6
- package/dist/lite/packages/firestore/src/lite-api/transaction.d.ts +2 -0
- package/dist/lite/packages/firestore/src/local/document_overlay_cache.d.ts +5 -0
- package/dist/lite/packages/firestore/src/local/index_backfiller.d.ts +44 -0
- package/dist/lite/packages/firestore/src/local/index_manager.d.ts +2 -0
- package/dist/lite/packages/firestore/src/local/indexeddb_document_overlay_cache.d.ts +1 -0
- package/dist/lite/packages/firestore/src/local/indexeddb_index_manager.d.ts +1 -0
- package/dist/lite/packages/firestore/src/local/indexeddb_schema.d.ts +3 -2
- package/dist/lite/packages/firestore/src/local/indexeddb_schema_converter.d.ts +1 -0
- package/dist/lite/packages/firestore/src/local/indexeddb_sentinels.d.ts +1 -0
- package/dist/lite/packages/firestore/src/local/local_documents_view.d.ts +64 -9
- package/dist/lite/packages/firestore/src/local/local_store.d.ts +9 -0
- package/dist/lite/packages/firestore/src/local/lru_garbage_collector_impl.d.ts +5 -5
- package/dist/lite/packages/firestore/src/local/memory_document_overlay_cache.d.ts +1 -0
- package/dist/lite/packages/firestore/src/local/memory_index_manager.d.ts +1 -0
- package/dist/lite/packages/firestore/src/local/overlayed_document.d.ts +36 -0
- package/dist/lite/packages/firestore/src/local/persistence.d.ts +3 -5
- package/dist/lite/packages/firestore/src/local/persistence_promise.d.ts +11 -0
- package/dist/lite/packages/firestore/src/local/query_engine.d.ts +1 -1
- package/dist/lite/packages/firestore/src/model/collections.d.ts +8 -2
- package/dist/lite/packages/firestore/src/model/field_mask.d.ts +6 -0
- package/dist/lite/packages/firestore/src/model/mutation.d.ts +19 -1
- package/dist/lite/packages/firestore/src/model/mutation_batch.d.ts +8 -4
- package/dist/lite/packages/firestore/src/util/async_queue.d.ts +5 -1
- package/dist/lite/packages/firestore/test/unit/local/index_backfiller.test.d.ts +17 -0
- package/dist/lite/packages/firestore/test/unit/local/test_document_overlay_cache.d.ts +1 -0
- package/dist/lite/packages/firestore/test/unit/specs/spec_test_components.d.ts +5 -3
- package/dist/lite/packages/firestore/test/util/helpers.d.ts +13 -0
- package/dist/lite/private.d.ts +2776 -2758
- package/dist/packages/firestore/dist/index.esm2017.d.ts +203 -201
- package/dist/packages/firestore/src/api/transaction.d.ts +2 -0
- package/dist/packages/firestore/src/core/component_provider.d.ts +11 -6
- package/dist/packages/firestore/src/lite-api/transaction.d.ts +2 -0
- package/dist/packages/firestore/src/local/document_overlay_cache.d.ts +5 -0
- package/dist/packages/firestore/src/local/index_backfiller.d.ts +44 -0
- package/dist/packages/firestore/src/local/index_manager.d.ts +2 -0
- package/dist/packages/firestore/src/local/indexeddb_document_overlay_cache.d.ts +1 -0
- package/dist/packages/firestore/src/local/indexeddb_index_manager.d.ts +1 -0
- package/dist/packages/firestore/src/local/indexeddb_schema.d.ts +3 -2
- package/dist/packages/firestore/src/local/indexeddb_schema_converter.d.ts +1 -0
- package/dist/packages/firestore/src/local/indexeddb_sentinels.d.ts +1 -0
- package/dist/packages/firestore/src/local/local_documents_view.d.ts +64 -9
- package/dist/packages/firestore/src/local/local_store.d.ts +9 -0
- package/dist/packages/firestore/src/local/lru_garbage_collector_impl.d.ts +5 -5
- package/dist/packages/firestore/src/local/memory_document_overlay_cache.d.ts +1 -0
- package/dist/packages/firestore/src/local/memory_index_manager.d.ts +1 -0
- package/dist/packages/firestore/src/local/overlayed_document.d.ts +36 -0
- package/dist/packages/firestore/src/local/persistence.d.ts +3 -5
- package/dist/packages/firestore/src/local/persistence_promise.d.ts +11 -0
- package/dist/packages/firestore/src/local/query_engine.d.ts +1 -1
- package/dist/packages/firestore/src/model/collections.d.ts +8 -2
- package/dist/packages/firestore/src/model/field_mask.d.ts +6 -0
- package/dist/packages/firestore/src/model/mutation.d.ts +19 -1
- package/dist/packages/firestore/src/model/mutation_batch.d.ts +8 -4
- package/dist/packages/firestore/src/util/async_queue.d.ts +5 -1
- package/dist/packages/firestore/test/unit/local/index_backfiller.test.d.ts +17 -0
- package/dist/packages/firestore/test/unit/local/test_document_overlay_cache.d.ts +1 -0
- package/dist/packages/firestore/test/unit/specs/spec_test_components.d.ts +5 -3
- package/dist/packages/firestore/test/util/helpers.d.ts +13 -0
- package/dist/private.d.ts +5845 -5672
- package/package.json +19 -17
package/dist/lite/index.node.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { FirebaseError, createMockUserToken, getModularInstance } from '@firebas
|
|
|
6
6
|
import nodeFetch from 'node-fetch';
|
|
7
7
|
import { randomBytes as randomBytes$1 } from 'crypto';
|
|
8
8
|
|
|
9
|
-
const version$1 = "3.4.
|
|
9
|
+
const version$1 = "3.4.10-canary.8e952e2ee";
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* @license
|
|
@@ -59,7 +59,7 @@ User.GOOGLE_CREDENTIALS = new User('google-credentials-uid');
|
|
|
59
59
|
User.FIRST_PARTY = new User('first-party-uid');
|
|
60
60
|
User.MOCK_USER = new User('mock-user');
|
|
61
61
|
|
|
62
|
-
const version = "9.8.
|
|
62
|
+
const version = "9.8.3-canary.8e952e2ee";
|
|
63
63
|
|
|
64
64
|
/**
|
|
65
65
|
* @license
|
|
@@ -1816,6 +1816,627 @@ function isEmpty(obj) {
|
|
|
1816
1816
|
return true;
|
|
1817
1817
|
}
|
|
1818
1818
|
|
|
1819
|
+
/**
|
|
1820
|
+
* @license
|
|
1821
|
+
* Copyright 2017 Google LLC
|
|
1822
|
+
*
|
|
1823
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
1824
|
+
* you may not use this file except in compliance with the License.
|
|
1825
|
+
* You may obtain a copy of the License at
|
|
1826
|
+
*
|
|
1827
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
1828
|
+
*
|
|
1829
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
1830
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
1831
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
1832
|
+
* See the License for the specific language governing permissions and
|
|
1833
|
+
* limitations under the License.
|
|
1834
|
+
*/
|
|
1835
|
+
// An immutable sorted map implementation, based on a Left-leaning Red-Black
|
|
1836
|
+
// tree.
|
|
1837
|
+
class SortedMap {
|
|
1838
|
+
constructor(comparator, root) {
|
|
1839
|
+
this.comparator = comparator;
|
|
1840
|
+
this.root = root ? root : LLRBNode.EMPTY;
|
|
1841
|
+
}
|
|
1842
|
+
// Returns a copy of the map, with the specified key/value added or replaced.
|
|
1843
|
+
insert(key, value) {
|
|
1844
|
+
return new SortedMap(this.comparator, this.root
|
|
1845
|
+
.insert(key, value, this.comparator)
|
|
1846
|
+
.copy(null, null, LLRBNode.BLACK, null, null));
|
|
1847
|
+
}
|
|
1848
|
+
// Returns a copy of the map, with the specified key removed.
|
|
1849
|
+
remove(key) {
|
|
1850
|
+
return new SortedMap(this.comparator, this.root
|
|
1851
|
+
.remove(key, this.comparator)
|
|
1852
|
+
.copy(null, null, LLRBNode.BLACK, null, null));
|
|
1853
|
+
}
|
|
1854
|
+
// Returns the value of the node with the given key, or null.
|
|
1855
|
+
get(key) {
|
|
1856
|
+
let node = this.root;
|
|
1857
|
+
while (!node.isEmpty()) {
|
|
1858
|
+
const cmp = this.comparator(key, node.key);
|
|
1859
|
+
if (cmp === 0) {
|
|
1860
|
+
return node.value;
|
|
1861
|
+
}
|
|
1862
|
+
else if (cmp < 0) {
|
|
1863
|
+
node = node.left;
|
|
1864
|
+
}
|
|
1865
|
+
else if (cmp > 0) {
|
|
1866
|
+
node = node.right;
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
return null;
|
|
1870
|
+
}
|
|
1871
|
+
// Returns the index of the element in this sorted map, or -1 if it doesn't
|
|
1872
|
+
// exist.
|
|
1873
|
+
indexOf(key) {
|
|
1874
|
+
// Number of nodes that were pruned when descending right
|
|
1875
|
+
let prunedNodes = 0;
|
|
1876
|
+
let node = this.root;
|
|
1877
|
+
while (!node.isEmpty()) {
|
|
1878
|
+
const cmp = this.comparator(key, node.key);
|
|
1879
|
+
if (cmp === 0) {
|
|
1880
|
+
return prunedNodes + node.left.size;
|
|
1881
|
+
}
|
|
1882
|
+
else if (cmp < 0) {
|
|
1883
|
+
node = node.left;
|
|
1884
|
+
}
|
|
1885
|
+
else {
|
|
1886
|
+
// Count all nodes left of the node plus the node itself
|
|
1887
|
+
prunedNodes += node.left.size + 1;
|
|
1888
|
+
node = node.right;
|
|
1889
|
+
}
|
|
1890
|
+
}
|
|
1891
|
+
// Node not found
|
|
1892
|
+
return -1;
|
|
1893
|
+
}
|
|
1894
|
+
isEmpty() {
|
|
1895
|
+
return this.root.isEmpty();
|
|
1896
|
+
}
|
|
1897
|
+
// Returns the total number of nodes in the map.
|
|
1898
|
+
get size() {
|
|
1899
|
+
return this.root.size;
|
|
1900
|
+
}
|
|
1901
|
+
// Returns the minimum key in the map.
|
|
1902
|
+
minKey() {
|
|
1903
|
+
return this.root.minKey();
|
|
1904
|
+
}
|
|
1905
|
+
// Returns the maximum key in the map.
|
|
1906
|
+
maxKey() {
|
|
1907
|
+
return this.root.maxKey();
|
|
1908
|
+
}
|
|
1909
|
+
// Traverses the map in key order and calls the specified action function
|
|
1910
|
+
// for each key/value pair. If action returns true, traversal is aborted.
|
|
1911
|
+
// Returns the first truthy value returned by action, or the last falsey
|
|
1912
|
+
// value returned by action.
|
|
1913
|
+
inorderTraversal(action) {
|
|
1914
|
+
return this.root.inorderTraversal(action);
|
|
1915
|
+
}
|
|
1916
|
+
forEach(fn) {
|
|
1917
|
+
this.inorderTraversal((k, v) => {
|
|
1918
|
+
fn(k, v);
|
|
1919
|
+
return false;
|
|
1920
|
+
});
|
|
1921
|
+
}
|
|
1922
|
+
toString() {
|
|
1923
|
+
const descriptions = [];
|
|
1924
|
+
this.inorderTraversal((k, v) => {
|
|
1925
|
+
descriptions.push(`${k}:${v}`);
|
|
1926
|
+
return false;
|
|
1927
|
+
});
|
|
1928
|
+
return `{${descriptions.join(', ')}}`;
|
|
1929
|
+
}
|
|
1930
|
+
// Traverses the map in reverse key order and calls the specified action
|
|
1931
|
+
// function for each key/value pair. If action returns true, traversal is
|
|
1932
|
+
// aborted.
|
|
1933
|
+
// Returns the first truthy value returned by action, or the last falsey
|
|
1934
|
+
// value returned by action.
|
|
1935
|
+
reverseTraversal(action) {
|
|
1936
|
+
return this.root.reverseTraversal(action);
|
|
1937
|
+
}
|
|
1938
|
+
// Returns an iterator over the SortedMap.
|
|
1939
|
+
getIterator() {
|
|
1940
|
+
return new SortedMapIterator(this.root, null, this.comparator, false);
|
|
1941
|
+
}
|
|
1942
|
+
getIteratorFrom(key) {
|
|
1943
|
+
return new SortedMapIterator(this.root, key, this.comparator, false);
|
|
1944
|
+
}
|
|
1945
|
+
getReverseIterator() {
|
|
1946
|
+
return new SortedMapIterator(this.root, null, this.comparator, true);
|
|
1947
|
+
}
|
|
1948
|
+
getReverseIteratorFrom(key) {
|
|
1949
|
+
return new SortedMapIterator(this.root, key, this.comparator, true);
|
|
1950
|
+
}
|
|
1951
|
+
} // end SortedMap
|
|
1952
|
+
// An iterator over an LLRBNode.
|
|
1953
|
+
class SortedMapIterator {
|
|
1954
|
+
constructor(node, startKey, comparator, isReverse) {
|
|
1955
|
+
this.isReverse = isReverse;
|
|
1956
|
+
this.nodeStack = [];
|
|
1957
|
+
let cmp = 1;
|
|
1958
|
+
while (!node.isEmpty()) {
|
|
1959
|
+
cmp = startKey ? comparator(node.key, startKey) : 1;
|
|
1960
|
+
// flip the comparison if we're going in reverse
|
|
1961
|
+
if (startKey && isReverse) {
|
|
1962
|
+
cmp *= -1;
|
|
1963
|
+
}
|
|
1964
|
+
if (cmp < 0) {
|
|
1965
|
+
// This node is less than our start key. ignore it
|
|
1966
|
+
if (this.isReverse) {
|
|
1967
|
+
node = node.left;
|
|
1968
|
+
}
|
|
1969
|
+
else {
|
|
1970
|
+
node = node.right;
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
else if (cmp === 0) {
|
|
1974
|
+
// This node is exactly equal to our start key. Push it on the stack,
|
|
1975
|
+
// but stop iterating;
|
|
1976
|
+
this.nodeStack.push(node);
|
|
1977
|
+
break;
|
|
1978
|
+
}
|
|
1979
|
+
else {
|
|
1980
|
+
// This node is greater than our start key, add it to the stack and move
|
|
1981
|
+
// to the next one
|
|
1982
|
+
this.nodeStack.push(node);
|
|
1983
|
+
if (this.isReverse) {
|
|
1984
|
+
node = node.right;
|
|
1985
|
+
}
|
|
1986
|
+
else {
|
|
1987
|
+
node = node.left;
|
|
1988
|
+
}
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
getNext() {
|
|
1993
|
+
let node = this.nodeStack.pop();
|
|
1994
|
+
const result = { key: node.key, value: node.value };
|
|
1995
|
+
if (this.isReverse) {
|
|
1996
|
+
node = node.left;
|
|
1997
|
+
while (!node.isEmpty()) {
|
|
1998
|
+
this.nodeStack.push(node);
|
|
1999
|
+
node = node.right;
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
else {
|
|
2003
|
+
node = node.right;
|
|
2004
|
+
while (!node.isEmpty()) {
|
|
2005
|
+
this.nodeStack.push(node);
|
|
2006
|
+
node = node.left;
|
|
2007
|
+
}
|
|
2008
|
+
}
|
|
2009
|
+
return result;
|
|
2010
|
+
}
|
|
2011
|
+
hasNext() {
|
|
2012
|
+
return this.nodeStack.length > 0;
|
|
2013
|
+
}
|
|
2014
|
+
peek() {
|
|
2015
|
+
if (this.nodeStack.length === 0) {
|
|
2016
|
+
return null;
|
|
2017
|
+
}
|
|
2018
|
+
const node = this.nodeStack[this.nodeStack.length - 1];
|
|
2019
|
+
return { key: node.key, value: node.value };
|
|
2020
|
+
}
|
|
2021
|
+
} // end SortedMapIterator
|
|
2022
|
+
// Represents a node in a Left-leaning Red-Black tree.
|
|
2023
|
+
class LLRBNode {
|
|
2024
|
+
constructor(key, value, color, left, right) {
|
|
2025
|
+
this.key = key;
|
|
2026
|
+
this.value = value;
|
|
2027
|
+
this.color = color != null ? color : LLRBNode.RED;
|
|
2028
|
+
this.left = left != null ? left : LLRBNode.EMPTY;
|
|
2029
|
+
this.right = right != null ? right : LLRBNode.EMPTY;
|
|
2030
|
+
this.size = this.left.size + 1 + this.right.size;
|
|
2031
|
+
}
|
|
2032
|
+
// Returns a copy of the current node, optionally replacing pieces of it.
|
|
2033
|
+
copy(key, value, color, left, right) {
|
|
2034
|
+
return new LLRBNode(key != null ? key : this.key, value != null ? value : this.value, color != null ? color : this.color, left != null ? left : this.left, right != null ? right : this.right);
|
|
2035
|
+
}
|
|
2036
|
+
isEmpty() {
|
|
2037
|
+
return false;
|
|
2038
|
+
}
|
|
2039
|
+
// Traverses the tree in key order and calls the specified action function
|
|
2040
|
+
// for each node. If action returns true, traversal is aborted.
|
|
2041
|
+
// Returns the first truthy value returned by action, or the last falsey
|
|
2042
|
+
// value returned by action.
|
|
2043
|
+
inorderTraversal(action) {
|
|
2044
|
+
return (this.left.inorderTraversal(action) ||
|
|
2045
|
+
action(this.key, this.value) ||
|
|
2046
|
+
this.right.inorderTraversal(action));
|
|
2047
|
+
}
|
|
2048
|
+
// Traverses the tree in reverse key order and calls the specified action
|
|
2049
|
+
// function for each node. If action returns true, traversal is aborted.
|
|
2050
|
+
// Returns the first truthy value returned by action, or the last falsey
|
|
2051
|
+
// value returned by action.
|
|
2052
|
+
reverseTraversal(action) {
|
|
2053
|
+
return (this.right.reverseTraversal(action) ||
|
|
2054
|
+
action(this.key, this.value) ||
|
|
2055
|
+
this.left.reverseTraversal(action));
|
|
2056
|
+
}
|
|
2057
|
+
// Returns the minimum node in the tree.
|
|
2058
|
+
min() {
|
|
2059
|
+
if (this.left.isEmpty()) {
|
|
2060
|
+
return this;
|
|
2061
|
+
}
|
|
2062
|
+
else {
|
|
2063
|
+
return this.left.min();
|
|
2064
|
+
}
|
|
2065
|
+
}
|
|
2066
|
+
// Returns the maximum key in the tree.
|
|
2067
|
+
minKey() {
|
|
2068
|
+
return this.min().key;
|
|
2069
|
+
}
|
|
2070
|
+
// Returns the maximum key in the tree.
|
|
2071
|
+
maxKey() {
|
|
2072
|
+
if (this.right.isEmpty()) {
|
|
2073
|
+
return this.key;
|
|
2074
|
+
}
|
|
2075
|
+
else {
|
|
2076
|
+
return this.right.maxKey();
|
|
2077
|
+
}
|
|
2078
|
+
}
|
|
2079
|
+
// Returns new tree, with the key/value added.
|
|
2080
|
+
insert(key, value, comparator) {
|
|
2081
|
+
let n = this;
|
|
2082
|
+
const cmp = comparator(key, n.key);
|
|
2083
|
+
if (cmp < 0) {
|
|
2084
|
+
n = n.copy(null, null, null, n.left.insert(key, value, comparator), null);
|
|
2085
|
+
}
|
|
2086
|
+
else if (cmp === 0) {
|
|
2087
|
+
n = n.copy(null, value, null, null, null);
|
|
2088
|
+
}
|
|
2089
|
+
else {
|
|
2090
|
+
n = n.copy(null, null, null, null, n.right.insert(key, value, comparator));
|
|
2091
|
+
}
|
|
2092
|
+
return n.fixUp();
|
|
2093
|
+
}
|
|
2094
|
+
removeMin() {
|
|
2095
|
+
if (this.left.isEmpty()) {
|
|
2096
|
+
return LLRBNode.EMPTY;
|
|
2097
|
+
}
|
|
2098
|
+
let n = this;
|
|
2099
|
+
if (!n.left.isRed() && !n.left.left.isRed()) {
|
|
2100
|
+
n = n.moveRedLeft();
|
|
2101
|
+
}
|
|
2102
|
+
n = n.copy(null, null, null, n.left.removeMin(), null);
|
|
2103
|
+
return n.fixUp();
|
|
2104
|
+
}
|
|
2105
|
+
// Returns new tree, with the specified item removed.
|
|
2106
|
+
remove(key, comparator) {
|
|
2107
|
+
let smallest;
|
|
2108
|
+
let n = this;
|
|
2109
|
+
if (comparator(key, n.key) < 0) {
|
|
2110
|
+
if (!n.left.isEmpty() && !n.left.isRed() && !n.left.left.isRed()) {
|
|
2111
|
+
n = n.moveRedLeft();
|
|
2112
|
+
}
|
|
2113
|
+
n = n.copy(null, null, null, n.left.remove(key, comparator), null);
|
|
2114
|
+
}
|
|
2115
|
+
else {
|
|
2116
|
+
if (n.left.isRed()) {
|
|
2117
|
+
n = n.rotateRight();
|
|
2118
|
+
}
|
|
2119
|
+
if (!n.right.isEmpty() && !n.right.isRed() && !n.right.left.isRed()) {
|
|
2120
|
+
n = n.moveRedRight();
|
|
2121
|
+
}
|
|
2122
|
+
if (comparator(key, n.key) === 0) {
|
|
2123
|
+
if (n.right.isEmpty()) {
|
|
2124
|
+
return LLRBNode.EMPTY;
|
|
2125
|
+
}
|
|
2126
|
+
else {
|
|
2127
|
+
smallest = n.right.min();
|
|
2128
|
+
n = n.copy(smallest.key, smallest.value, null, null, n.right.removeMin());
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
2131
|
+
n = n.copy(null, null, null, null, n.right.remove(key, comparator));
|
|
2132
|
+
}
|
|
2133
|
+
return n.fixUp();
|
|
2134
|
+
}
|
|
2135
|
+
isRed() {
|
|
2136
|
+
return this.color;
|
|
2137
|
+
}
|
|
2138
|
+
// Returns new tree after performing any needed rotations.
|
|
2139
|
+
fixUp() {
|
|
2140
|
+
let n = this;
|
|
2141
|
+
if (n.right.isRed() && !n.left.isRed()) {
|
|
2142
|
+
n = n.rotateLeft();
|
|
2143
|
+
}
|
|
2144
|
+
if (n.left.isRed() && n.left.left.isRed()) {
|
|
2145
|
+
n = n.rotateRight();
|
|
2146
|
+
}
|
|
2147
|
+
if (n.left.isRed() && n.right.isRed()) {
|
|
2148
|
+
n = n.colorFlip();
|
|
2149
|
+
}
|
|
2150
|
+
return n;
|
|
2151
|
+
}
|
|
2152
|
+
moveRedLeft() {
|
|
2153
|
+
let n = this.colorFlip();
|
|
2154
|
+
if (n.right.left.isRed()) {
|
|
2155
|
+
n = n.copy(null, null, null, null, n.right.rotateRight());
|
|
2156
|
+
n = n.rotateLeft();
|
|
2157
|
+
n = n.colorFlip();
|
|
2158
|
+
}
|
|
2159
|
+
return n;
|
|
2160
|
+
}
|
|
2161
|
+
moveRedRight() {
|
|
2162
|
+
let n = this.colorFlip();
|
|
2163
|
+
if (n.left.left.isRed()) {
|
|
2164
|
+
n = n.rotateRight();
|
|
2165
|
+
n = n.colorFlip();
|
|
2166
|
+
}
|
|
2167
|
+
return n;
|
|
2168
|
+
}
|
|
2169
|
+
rotateLeft() {
|
|
2170
|
+
const nl = this.copy(null, null, LLRBNode.RED, null, this.right.left);
|
|
2171
|
+
return this.right.copy(null, null, this.color, nl, null);
|
|
2172
|
+
}
|
|
2173
|
+
rotateRight() {
|
|
2174
|
+
const nr = this.copy(null, null, LLRBNode.RED, this.left.right, null);
|
|
2175
|
+
return this.left.copy(null, null, this.color, null, nr);
|
|
2176
|
+
}
|
|
2177
|
+
colorFlip() {
|
|
2178
|
+
const left = this.left.copy(null, null, !this.left.color, null, null);
|
|
2179
|
+
const right = this.right.copy(null, null, !this.right.color, null, null);
|
|
2180
|
+
return this.copy(null, null, !this.color, left, right);
|
|
2181
|
+
}
|
|
2182
|
+
// For testing.
|
|
2183
|
+
checkMaxDepth() {
|
|
2184
|
+
const blackDepth = this.check();
|
|
2185
|
+
if (Math.pow(2.0, blackDepth) <= this.size + 1) {
|
|
2186
|
+
return true;
|
|
2187
|
+
}
|
|
2188
|
+
else {
|
|
2189
|
+
return false;
|
|
2190
|
+
}
|
|
2191
|
+
}
|
|
2192
|
+
// In a balanced RB tree, the black-depth (number of black nodes) from root to
|
|
2193
|
+
// leaves is equal on both sides. This function verifies that or asserts.
|
|
2194
|
+
check() {
|
|
2195
|
+
if (this.isRed() && this.left.isRed()) {
|
|
2196
|
+
throw fail();
|
|
2197
|
+
}
|
|
2198
|
+
if (this.right.isRed()) {
|
|
2199
|
+
throw fail();
|
|
2200
|
+
}
|
|
2201
|
+
const blackDepth = this.left.check();
|
|
2202
|
+
if (blackDepth !== this.right.check()) {
|
|
2203
|
+
throw fail();
|
|
2204
|
+
}
|
|
2205
|
+
else {
|
|
2206
|
+
return blackDepth + (this.isRed() ? 0 : 1);
|
|
2207
|
+
}
|
|
2208
|
+
}
|
|
2209
|
+
} // end LLRBNode
|
|
2210
|
+
// Empty node is shared between all LLRB trees.
|
|
2211
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2212
|
+
LLRBNode.EMPTY = null;
|
|
2213
|
+
LLRBNode.RED = true;
|
|
2214
|
+
LLRBNode.BLACK = false;
|
|
2215
|
+
// Represents an empty node (a leaf node in the Red-Black Tree).
|
|
2216
|
+
class LLRBEmptyNode {
|
|
2217
|
+
constructor() {
|
|
2218
|
+
this.size = 0;
|
|
2219
|
+
}
|
|
2220
|
+
get key() {
|
|
2221
|
+
throw fail();
|
|
2222
|
+
}
|
|
2223
|
+
get value() {
|
|
2224
|
+
throw fail();
|
|
2225
|
+
}
|
|
2226
|
+
get color() {
|
|
2227
|
+
throw fail();
|
|
2228
|
+
}
|
|
2229
|
+
get left() {
|
|
2230
|
+
throw fail();
|
|
2231
|
+
}
|
|
2232
|
+
get right() {
|
|
2233
|
+
throw fail();
|
|
2234
|
+
}
|
|
2235
|
+
// Returns a copy of the current node.
|
|
2236
|
+
copy(key, value, color, left, right) {
|
|
2237
|
+
return this;
|
|
2238
|
+
}
|
|
2239
|
+
// Returns a copy of the tree, with the specified key/value added.
|
|
2240
|
+
insert(key, value, comparator) {
|
|
2241
|
+
return new LLRBNode(key, value);
|
|
2242
|
+
}
|
|
2243
|
+
// Returns a copy of the tree, with the specified key removed.
|
|
2244
|
+
remove(key, comparator) {
|
|
2245
|
+
return this;
|
|
2246
|
+
}
|
|
2247
|
+
isEmpty() {
|
|
2248
|
+
return true;
|
|
2249
|
+
}
|
|
2250
|
+
inorderTraversal(action) {
|
|
2251
|
+
return false;
|
|
2252
|
+
}
|
|
2253
|
+
reverseTraversal(action) {
|
|
2254
|
+
return false;
|
|
2255
|
+
}
|
|
2256
|
+
minKey() {
|
|
2257
|
+
return null;
|
|
2258
|
+
}
|
|
2259
|
+
maxKey() {
|
|
2260
|
+
return null;
|
|
2261
|
+
}
|
|
2262
|
+
isRed() {
|
|
2263
|
+
return false;
|
|
2264
|
+
}
|
|
2265
|
+
// For testing.
|
|
2266
|
+
checkMaxDepth() {
|
|
2267
|
+
return true;
|
|
2268
|
+
}
|
|
2269
|
+
check() {
|
|
2270
|
+
return 0;
|
|
2271
|
+
}
|
|
2272
|
+
} // end LLRBEmptyNode
|
|
2273
|
+
LLRBNode.EMPTY = new LLRBEmptyNode();
|
|
2274
|
+
|
|
2275
|
+
/**
|
|
2276
|
+
* @license
|
|
2277
|
+
* Copyright 2017 Google LLC
|
|
2278
|
+
*
|
|
2279
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
2280
|
+
* you may not use this file except in compliance with the License.
|
|
2281
|
+
* You may obtain a copy of the License at
|
|
2282
|
+
*
|
|
2283
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
2284
|
+
*
|
|
2285
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
2286
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
2287
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
2288
|
+
* See the License for the specific language governing permissions and
|
|
2289
|
+
* limitations under the License.
|
|
2290
|
+
*/
|
|
2291
|
+
/**
|
|
2292
|
+
* SortedSet is an immutable (copy-on-write) collection that holds elements
|
|
2293
|
+
* in order specified by the provided comparator.
|
|
2294
|
+
*
|
|
2295
|
+
* NOTE: if provided comparator returns 0 for two elements, we consider them to
|
|
2296
|
+
* be equal!
|
|
2297
|
+
*/
|
|
2298
|
+
class SortedSet {
|
|
2299
|
+
constructor(comparator) {
|
|
2300
|
+
this.comparator = comparator;
|
|
2301
|
+
this.data = new SortedMap(this.comparator);
|
|
2302
|
+
}
|
|
2303
|
+
has(elem) {
|
|
2304
|
+
return this.data.get(elem) !== null;
|
|
2305
|
+
}
|
|
2306
|
+
first() {
|
|
2307
|
+
return this.data.minKey();
|
|
2308
|
+
}
|
|
2309
|
+
last() {
|
|
2310
|
+
return this.data.maxKey();
|
|
2311
|
+
}
|
|
2312
|
+
get size() {
|
|
2313
|
+
return this.data.size;
|
|
2314
|
+
}
|
|
2315
|
+
indexOf(elem) {
|
|
2316
|
+
return this.data.indexOf(elem);
|
|
2317
|
+
}
|
|
2318
|
+
/** Iterates elements in order defined by "comparator" */
|
|
2319
|
+
forEach(cb) {
|
|
2320
|
+
this.data.inorderTraversal((k, v) => {
|
|
2321
|
+
cb(k);
|
|
2322
|
+
return false;
|
|
2323
|
+
});
|
|
2324
|
+
}
|
|
2325
|
+
/** Iterates over `elem`s such that: range[0] <= elem < range[1]. */
|
|
2326
|
+
forEachInRange(range, cb) {
|
|
2327
|
+
const iter = this.data.getIteratorFrom(range[0]);
|
|
2328
|
+
while (iter.hasNext()) {
|
|
2329
|
+
const elem = iter.getNext();
|
|
2330
|
+
if (this.comparator(elem.key, range[1]) >= 0) {
|
|
2331
|
+
return;
|
|
2332
|
+
}
|
|
2333
|
+
cb(elem.key);
|
|
2334
|
+
}
|
|
2335
|
+
}
|
|
2336
|
+
/**
|
|
2337
|
+
* Iterates over `elem`s such that: start <= elem until false is returned.
|
|
2338
|
+
*/
|
|
2339
|
+
forEachWhile(cb, start) {
|
|
2340
|
+
let iter;
|
|
2341
|
+
if (start !== undefined) {
|
|
2342
|
+
iter = this.data.getIteratorFrom(start);
|
|
2343
|
+
}
|
|
2344
|
+
else {
|
|
2345
|
+
iter = this.data.getIterator();
|
|
2346
|
+
}
|
|
2347
|
+
while (iter.hasNext()) {
|
|
2348
|
+
const elem = iter.getNext();
|
|
2349
|
+
const result = cb(elem.key);
|
|
2350
|
+
if (!result) {
|
|
2351
|
+
return;
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
}
|
|
2355
|
+
/** Finds the least element greater than or equal to `elem`. */
|
|
2356
|
+
firstAfterOrEqual(elem) {
|
|
2357
|
+
const iter = this.data.getIteratorFrom(elem);
|
|
2358
|
+
return iter.hasNext() ? iter.getNext().key : null;
|
|
2359
|
+
}
|
|
2360
|
+
getIterator() {
|
|
2361
|
+
return new SortedSetIterator(this.data.getIterator());
|
|
2362
|
+
}
|
|
2363
|
+
getIteratorFrom(key) {
|
|
2364
|
+
return new SortedSetIterator(this.data.getIteratorFrom(key));
|
|
2365
|
+
}
|
|
2366
|
+
/** Inserts or updates an element */
|
|
2367
|
+
add(elem) {
|
|
2368
|
+
return this.copy(this.data.remove(elem).insert(elem, true));
|
|
2369
|
+
}
|
|
2370
|
+
/** Deletes an element */
|
|
2371
|
+
delete(elem) {
|
|
2372
|
+
if (!this.has(elem)) {
|
|
2373
|
+
return this;
|
|
2374
|
+
}
|
|
2375
|
+
return this.copy(this.data.remove(elem));
|
|
2376
|
+
}
|
|
2377
|
+
isEmpty() {
|
|
2378
|
+
return this.data.isEmpty();
|
|
2379
|
+
}
|
|
2380
|
+
unionWith(other) {
|
|
2381
|
+
let result = this;
|
|
2382
|
+
// Make sure `result` always refers to the larger one of the two sets.
|
|
2383
|
+
if (result.size < other.size) {
|
|
2384
|
+
result = other;
|
|
2385
|
+
other = this;
|
|
2386
|
+
}
|
|
2387
|
+
other.forEach(elem => {
|
|
2388
|
+
result = result.add(elem);
|
|
2389
|
+
});
|
|
2390
|
+
return result;
|
|
2391
|
+
}
|
|
2392
|
+
isEqual(other) {
|
|
2393
|
+
if (!(other instanceof SortedSet)) {
|
|
2394
|
+
return false;
|
|
2395
|
+
}
|
|
2396
|
+
if (this.size !== other.size) {
|
|
2397
|
+
return false;
|
|
2398
|
+
}
|
|
2399
|
+
const thisIt = this.data.getIterator();
|
|
2400
|
+
const otherIt = other.data.getIterator();
|
|
2401
|
+
while (thisIt.hasNext()) {
|
|
2402
|
+
const thisElem = thisIt.getNext().key;
|
|
2403
|
+
const otherElem = otherIt.getNext().key;
|
|
2404
|
+
if (this.comparator(thisElem, otherElem) !== 0) {
|
|
2405
|
+
return false;
|
|
2406
|
+
}
|
|
2407
|
+
}
|
|
2408
|
+
return true;
|
|
2409
|
+
}
|
|
2410
|
+
toArray() {
|
|
2411
|
+
const res = [];
|
|
2412
|
+
this.forEach(targetId => {
|
|
2413
|
+
res.push(targetId);
|
|
2414
|
+
});
|
|
2415
|
+
return res;
|
|
2416
|
+
}
|
|
2417
|
+
toString() {
|
|
2418
|
+
const result = [];
|
|
2419
|
+
this.forEach(elem => result.push(elem));
|
|
2420
|
+
return 'SortedSet(' + result.toString() + ')';
|
|
2421
|
+
}
|
|
2422
|
+
copy(data) {
|
|
2423
|
+
const result = new SortedSet(this.comparator);
|
|
2424
|
+
result.data = data;
|
|
2425
|
+
return result;
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
class SortedSetIterator {
|
|
2429
|
+
constructor(iter) {
|
|
2430
|
+
this.iter = iter;
|
|
2431
|
+
}
|
|
2432
|
+
getNext() {
|
|
2433
|
+
return this.iter.getNext().key;
|
|
2434
|
+
}
|
|
2435
|
+
hasNext() {
|
|
2436
|
+
return this.iter.hasNext();
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2439
|
+
|
|
1819
2440
|
/**
|
|
1820
2441
|
* @license
|
|
1821
2442
|
* Copyright 2020 Google LLC
|
|
@@ -1849,6 +2470,23 @@ class FieldMask {
|
|
|
1849
2470
|
// Sort the field mask to support `FieldMask.isEqual()` and assert below.
|
|
1850
2471
|
fields.sort(FieldPath$1.comparator);
|
|
1851
2472
|
}
|
|
2473
|
+
static empty() {
|
|
2474
|
+
return new FieldMask([]);
|
|
2475
|
+
}
|
|
2476
|
+
/**
|
|
2477
|
+
* Returns a new FieldMask object that is the result of adding all the given
|
|
2478
|
+
* fields paths to this field mask.
|
|
2479
|
+
*/
|
|
2480
|
+
unionWith(extraFields) {
|
|
2481
|
+
let mergedMaskSet = new SortedSet(FieldPath$1.comparator);
|
|
2482
|
+
for (const fieldPath of this.fields) {
|
|
2483
|
+
mergedMaskSet = mergedMaskSet.add(fieldPath);
|
|
2484
|
+
}
|
|
2485
|
+
for (const fieldPath of extraFields) {
|
|
2486
|
+
mergedMaskSet = mergedMaskSet.add(fieldPath);
|
|
2487
|
+
}
|
|
2488
|
+
return new FieldMask(mergedMaskSet.toArray());
|
|
2489
|
+
}
|
|
1852
2490
|
/**
|
|
1853
2491
|
* Verifies that `fieldPath` is included by at least one field in this field
|
|
1854
2492
|
* mask.
|
|
@@ -2760,6 +3398,7 @@ class MutableDocument {
|
|
|
2760
3398
|
}
|
|
2761
3399
|
setHasLocalMutations() {
|
|
2762
3400
|
this.documentState = 1 /* HAS_LOCAL_MUTATIONS */;
|
|
3401
|
+
this.version = SnapshotVersion.min();
|
|
2763
3402
|
return this;
|
|
2764
3403
|
}
|
|
2765
3404
|
setReadTime(readTime) {
|
|
@@ -3501,6 +4140,9 @@ class SetMutation extends Mutation {
|
|
|
3501
4140
|
this.fieldTransforms = fieldTransforms;
|
|
3502
4141
|
this.type = 0 /* Set */;
|
|
3503
4142
|
}
|
|
4143
|
+
getFieldMask() {
|
|
4144
|
+
return null;
|
|
4145
|
+
}
|
|
3504
4146
|
}
|
|
3505
4147
|
/**
|
|
3506
4148
|
* A mutation that modifies fields of the document at the given key with the
|
|
@@ -3525,6 +4167,9 @@ class PatchMutation extends Mutation {
|
|
|
3525
4167
|
this.fieldTransforms = fieldTransforms;
|
|
3526
4168
|
this.type = 1 /* Patch */;
|
|
3527
4169
|
}
|
|
4170
|
+
getFieldMask() {
|
|
4171
|
+
return this.fieldMask;
|
|
4172
|
+
}
|
|
3528
4173
|
}
|
|
3529
4174
|
/** A mutation that deletes the document at the given key. */
|
|
3530
4175
|
class DeleteMutation extends Mutation {
|
|
@@ -3535,6 +4180,9 @@ class DeleteMutation extends Mutation {
|
|
|
3535
4180
|
this.type = 2 /* Delete */;
|
|
3536
4181
|
this.fieldTransforms = [];
|
|
3537
4182
|
}
|
|
4183
|
+
getFieldMask() {
|
|
4184
|
+
return null;
|
|
4185
|
+
}
|
|
3538
4186
|
}
|
|
3539
4187
|
/**
|
|
3540
4188
|
* A mutation that verifies the existence of the document at the given key with
|
|
@@ -3551,6 +4199,9 @@ class VerifyMutation extends Mutation {
|
|
|
3551
4199
|
this.type = 3 /* Verify */;
|
|
3552
4200
|
this.fieldTransforms = [];
|
|
3553
4201
|
}
|
|
4202
|
+
getFieldMask() {
|
|
4203
|
+
return null;
|
|
4204
|
+
}
|
|
3554
4205
|
}
|
|
3555
4206
|
|
|
3556
4207
|
/**
|
|
@@ -7754,6 +8405,8 @@ class Transaction {
|
|
|
7754
8405
|
* transaction against.
|
|
7755
8406
|
* @param updateFunction - The function to execute within the transaction
|
|
7756
8407
|
* context.
|
|
8408
|
+
* @param options - An options object to configure maximum number of attempts to
|
|
8409
|
+
* commit.
|
|
7757
8410
|
* @returns If the transaction completed successfully or was explicitly aborted
|
|
7758
8411
|
* (the `updateFunction` returned a failed promise), the promise returned by the
|
|
7759
8412
|
* `updateFunction `is returned here. Otherwise, if the transaction failed, a
|