@react-native-firebase/app 20.1.0 → 20.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseVersion.java +1 -1
  3. package/ios/RNFBApp/RNFBVersion.m +1 -1
  4. package/lib/common/index.js +2 -0
  5. package/lib/index.d.ts +1 -0
  6. package/lib/internal/RNFBNativeEventEmitter.js +31 -6
  7. package/lib/internal/nativeModule.android.js +2 -0
  8. package/lib/internal/nativeModule.ios.js +2 -0
  9. package/lib/internal/nativeModule.js +4 -0
  10. package/lib/internal/nativeModuleAndroidIos.js +45 -0
  11. package/lib/internal/nativeModuleWeb.js +48 -0
  12. package/lib/internal/registry/app.js +2 -1
  13. package/lib/internal/registry/nativeModule.js +11 -15
  14. package/lib/internal/web/RNFBAppModule.js +266 -0
  15. package/lib/internal/web/firebaseApp.js +3 -0
  16. package/lib/internal/web/firebaseAppCheck.js +6 -0
  17. package/lib/internal/web/firebaseAuth.js +4 -0
  18. package/lib/internal/web/firebaseDatabase.js +4 -0
  19. package/lib/internal/web/firebaseFirestore.js +4 -0
  20. package/lib/internal/web/firebaseFunctions.js +4 -0
  21. package/lib/internal/web/firebaseInstallations.js +6 -0
  22. package/lib/internal/web/firebaseRemoteConfig.js +6 -0
  23. package/lib/internal/web/firebaseStorage.js +4 -0
  24. package/lib/internal/web/memidb/FDBCursor.js +503 -0
  25. package/lib/internal/web/memidb/FDBCursorWithValue.js +11 -0
  26. package/lib/internal/web/memidb/FDBDatabase.js +172 -0
  27. package/lib/internal/web/memidb/FDBFactory.js +256 -0
  28. package/lib/internal/web/memidb/FDBIndex.js +187 -0
  29. package/lib/internal/web/memidb/FDBKeyRange.js +71 -0
  30. package/lib/internal/web/memidb/FDBObjectStore.js +411 -0
  31. package/lib/internal/web/memidb/FDBOpenDBRequest.js +9 -0
  32. package/lib/internal/web/memidb/FDBRequest.js +33 -0
  33. package/lib/internal/web/memidb/FDBTransaction.js +216 -0
  34. package/lib/internal/web/memidb/FDBVersionChangeEvent.js +12 -0
  35. package/lib/internal/web/memidb/LICENSE +208 -0
  36. package/lib/internal/web/memidb/index.js +39 -0
  37. package/lib/internal/web/memidb/lib/Database.js +32 -0
  38. package/lib/internal/web/memidb/lib/FakeDOMStringList.js +72 -0
  39. package/lib/internal/web/memidb/lib/FakeEvent.js +38 -0
  40. package/lib/internal/web/memidb/lib/FakeEventTarget.js +110 -0
  41. package/lib/internal/web/memidb/lib/Index.js +157 -0
  42. package/lib/internal/web/memidb/lib/KeyGenerator.js +22 -0
  43. package/lib/internal/web/memidb/lib/ObjectStore.js +172 -0
  44. package/lib/internal/web/memidb/lib/RecordStore.js +141 -0
  45. package/lib/internal/web/memidb/lib/binarySearch.js +78 -0
  46. package/lib/internal/web/memidb/lib/canInjectKey.js +25 -0
  47. package/lib/internal/web/memidb/lib/cmp.js +77 -0
  48. package/lib/internal/web/memidb/lib/enforceRange.js +13 -0
  49. package/lib/internal/web/memidb/lib/errors.js +69 -0
  50. package/lib/internal/web/memidb/lib/extractKey.js +39 -0
  51. package/lib/internal/web/memidb/lib/scheduling.js +30 -0
  52. package/lib/internal/web/memidb/lib/types.js +1 -0
  53. package/lib/internal/web/memidb/lib/validateKeyPath.js +54 -0
  54. package/lib/internal/web/memidb/lib/valueToKey.js +62 -0
  55. package/lib/internal/web/memidb/lib/valueToKeyRange.js +19 -0
  56. package/lib/internal/web/structuredClone/index.js +222 -0
  57. package/lib/internal/web/utils.js +35 -0
  58. package/lib/utils/UtilsStatics.js +3 -2
  59. package/lib/version.js +1 -1
  60. package/package.json +8 -7
@@ -0,0 +1,172 @@
1
+ import { ConstraintError, DataError } from './errors.js';
2
+ import extractKey from './extractKey.js';
3
+ import KeyGenerator from './KeyGenerator.js';
4
+ import RecordStore from './RecordStore.js';
5
+ // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-object-store
6
+ class ObjectStore {
7
+ deleted = false;
8
+ records = new RecordStore();
9
+ rawIndexes = new Map();
10
+ constructor(rawDatabase, name, keyPath, autoIncrement) {
11
+ this.rawDatabase = rawDatabase;
12
+ this.keyGenerator = autoIncrement === true ? new KeyGenerator() : null;
13
+ this.deleted = false;
14
+ this.name = name;
15
+ this.keyPath = keyPath;
16
+ this.autoIncrement = autoIncrement;
17
+ }
18
+
19
+ // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-for-retrieving-a-value-from-an-object-store
20
+ getKey(key) {
21
+ const record = this.records.get(key);
22
+ return record !== undefined ? structuredClone(record.key) : undefined;
23
+ }
24
+
25
+ // http://w3c.github.io/IndexedDB/#retrieve-multiple-keys-from-an-object-store
26
+ getAllKeys(range, count) {
27
+ if (count === undefined || count === 0) {
28
+ count = Infinity;
29
+ }
30
+ const records = [];
31
+ for (const record of this.records.values(range)) {
32
+ records.push(structuredClone(record.key));
33
+ if (records.length >= count) {
34
+ break;
35
+ }
36
+ }
37
+ return records;
38
+ }
39
+
40
+ // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-for-retrieving-a-value-from-an-object-store
41
+ getValue(key) {
42
+ const record = this.records.get(key);
43
+ return record !== undefined ? structuredClone(record.value) : undefined;
44
+ }
45
+
46
+ // http://w3c.github.io/IndexedDB/#retrieve-multiple-values-from-an-object-store
47
+ getAllValues(range, count) {
48
+ if (count === undefined || count === 0) {
49
+ count = Infinity;
50
+ }
51
+ const records = [];
52
+ for (const record of this.records.values(range)) {
53
+ records.push(structuredClone(record.value));
54
+ if (records.length >= count) {
55
+ break;
56
+ }
57
+ }
58
+ return records;
59
+ }
60
+
61
+ // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-for-storing-a-record-into-an-object-store
62
+ storeRecord(newRecord, noOverwrite, rollbackLog) {
63
+ if (this.keyPath !== null) {
64
+ const key = extractKey(this.keyPath, newRecord.value);
65
+ if (key !== undefined) {
66
+ newRecord.key = key;
67
+ }
68
+ }
69
+ if (this.keyGenerator !== null && newRecord.key === undefined) {
70
+ if (rollbackLog) {
71
+ const keyGeneratorBefore = this.keyGenerator.num;
72
+ rollbackLog.push(() => {
73
+ if (this.keyGenerator) {
74
+ this.keyGenerator.num = keyGeneratorBefore;
75
+ }
76
+ });
77
+ }
78
+ newRecord.key = this.keyGenerator.next();
79
+
80
+ // Set in value if keyPath defiend but led to no key
81
+ // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-to-assign-a-key-to-a-value-using-a-key-path
82
+ if (this.keyPath !== null) {
83
+ if (Array.isArray(this.keyPath)) {
84
+ throw new Error('Cannot have an array key path in an object store with a key generator');
85
+ }
86
+ let remainingKeyPath = this.keyPath;
87
+ let object = newRecord.value;
88
+ let identifier;
89
+ let i = 0; // Just to run the loop at least once
90
+ while (i >= 0) {
91
+ if (typeof object !== 'object') {
92
+ throw new DataError();
93
+ }
94
+ i = remainingKeyPath.indexOf('.');
95
+ if (i >= 0) {
96
+ identifier = remainingKeyPath.slice(0, i);
97
+ remainingKeyPath = remainingKeyPath.slice(i + 1);
98
+ if (!Object.hasOwn(object, identifier)) {
99
+ object[identifier] = {};
100
+ }
101
+ object = object[identifier];
102
+ }
103
+ }
104
+ identifier = remainingKeyPath;
105
+ object[identifier] = newRecord.key;
106
+ }
107
+ } else if (this.keyGenerator !== null && typeof newRecord.key === 'number') {
108
+ this.keyGenerator.setIfLarger(newRecord.key);
109
+ }
110
+ const existingRecord = this.records.get(newRecord.key);
111
+ if (existingRecord) {
112
+ if (noOverwrite) {
113
+ throw new ConstraintError();
114
+ }
115
+ this.deleteRecord(newRecord.key, rollbackLog);
116
+ }
117
+ this.records.add(newRecord);
118
+ if (rollbackLog) {
119
+ rollbackLog.push(() => {
120
+ this.deleteRecord(newRecord.key);
121
+ });
122
+ }
123
+
124
+ // Update indexes
125
+ for (const rawIndex of this.rawIndexes.values()) {
126
+ if (rawIndex.initialized) {
127
+ rawIndex.storeRecord(newRecord);
128
+ }
129
+ }
130
+ return newRecord.key;
131
+ }
132
+
133
+ // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-for-deleting-records-from-an-object-store
134
+ deleteRecord(key, rollbackLog) {
135
+ const deletedRecords = this.records.delete(key);
136
+ if (rollbackLog) {
137
+ for (const record of deletedRecords) {
138
+ rollbackLog.push(() => {
139
+ this.storeRecord(record, true);
140
+ });
141
+ }
142
+ }
143
+ for (const rawIndex of this.rawIndexes.values()) {
144
+ rawIndex.records.deleteByValue(key);
145
+ }
146
+ }
147
+
148
+ // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-for-clearing-an-object-store
149
+ clear(rollbackLog) {
150
+ const deletedRecords = this.records.clear();
151
+ if (rollbackLog) {
152
+ for (const record of deletedRecords) {
153
+ rollbackLog.push(() => {
154
+ this.storeRecord(record, true);
155
+ });
156
+ }
157
+ }
158
+ for (const rawIndex of this.rawIndexes.values()) {
159
+ rawIndex.records.clear();
160
+ }
161
+ }
162
+ count(range) {
163
+ let count = 0;
164
+
165
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
166
+ for (const record of this.records.values(range)) {
167
+ count += 1;
168
+ }
169
+ return count;
170
+ }
171
+ }
172
+ export default ObjectStore;
@@ -0,0 +1,141 @@
1
+ import FDBKeyRange from '../FDBKeyRange.js';
2
+ import {
3
+ getByKey,
4
+ getByKeyRange,
5
+ getIndexByKey,
6
+ getIndexByKeyGTE,
7
+ getIndexByKeyRange,
8
+ } from './binarySearch.js';
9
+ import cmp from './cmp.js';
10
+ class RecordStore {
11
+ records = [];
12
+ get(key) {
13
+ if (key instanceof FDBKeyRange) {
14
+ return getByKeyRange(this.records, key);
15
+ }
16
+ return getByKey(this.records, key);
17
+ }
18
+ add(newRecord) {
19
+ // Find where to put it so it's sorted by key
20
+ let i;
21
+ if (this.records.length === 0) {
22
+ i = 0;
23
+ } else {
24
+ i = getIndexByKeyGTE(this.records, newRecord.key);
25
+ if (i === -1) {
26
+ // If no matching key, add to end
27
+ i = this.records.length;
28
+ } else {
29
+ // If matching key, advance to appropriate position based on value (used in indexes)
30
+ while (i < this.records.length && cmp(this.records[i].key, newRecord.key) === 0) {
31
+ if (cmp(this.records[i].value, newRecord.value) !== -1) {
32
+ // Record value >= newRecord value, so insert here
33
+ break;
34
+ }
35
+ i += 1; // Look at next record
36
+ }
37
+ }
38
+ }
39
+ this.records.splice(i, 0, newRecord);
40
+ }
41
+ delete(key) {
42
+ const deletedRecords = [];
43
+ const isRange = key instanceof FDBKeyRange;
44
+ while (true) {
45
+ const idx = isRange
46
+ ? getIndexByKeyRange(this.records, key)
47
+ : getIndexByKey(this.records, key);
48
+ if (idx === -1) {
49
+ break;
50
+ }
51
+ deletedRecords.push(this.records[idx]);
52
+ this.records.splice(idx, 1);
53
+ }
54
+ return deletedRecords;
55
+ }
56
+ deleteByValue(key) {
57
+ const range = key instanceof FDBKeyRange ? key : FDBKeyRange.only(key);
58
+ const deletedRecords = [];
59
+ this.records = this.records.filter(record => {
60
+ const shouldDelete = range.includes(record.value);
61
+ if (shouldDelete) {
62
+ deletedRecords.push(record);
63
+ }
64
+ return !shouldDelete;
65
+ });
66
+ return deletedRecords;
67
+ }
68
+ clear() {
69
+ const deletedRecords = this.records.slice();
70
+ this.records = [];
71
+ return deletedRecords;
72
+ }
73
+ values(range, direction = 'next') {
74
+ return {
75
+ [Symbol.iterator]: () => {
76
+ let i;
77
+ if (direction === 'next') {
78
+ i = 0;
79
+ if (range !== undefined && range.lower !== undefined) {
80
+ while (this.records[i] !== undefined) {
81
+ const cmpResult = cmp(this.records[i].key, range.lower);
82
+ if (cmpResult === 1 || (cmpResult === 0 && !range.lowerOpen)) {
83
+ break;
84
+ }
85
+ i += 1;
86
+ }
87
+ }
88
+ } else {
89
+ i = this.records.length - 1;
90
+ if (range !== undefined && range.upper !== undefined) {
91
+ while (this.records[i] !== undefined) {
92
+ const cmpResult = cmp(this.records[i].key, range.upper);
93
+ if (cmpResult === -1 || (cmpResult === 0 && !range.upperOpen)) {
94
+ break;
95
+ }
96
+ i -= 1;
97
+ }
98
+ }
99
+ }
100
+ return {
101
+ next: () => {
102
+ let done;
103
+ let value;
104
+ if (direction === 'next') {
105
+ value = this.records[i];
106
+ done = i >= this.records.length;
107
+ i += 1;
108
+ if (!done && range !== undefined && range.upper !== undefined) {
109
+ const cmpResult = cmp(value.key, range.upper);
110
+ done = cmpResult === 1 || (cmpResult === 0 && range.upperOpen);
111
+ if (done) {
112
+ value = undefined;
113
+ }
114
+ }
115
+ } else {
116
+ value = this.records[i];
117
+ done = i < 0;
118
+ i -= 1;
119
+ if (!done && range !== undefined && range.lower !== undefined) {
120
+ const cmpResult = cmp(value.key, range.lower);
121
+ done = cmpResult === -1 || (cmpResult === 0 && range.lowerOpen);
122
+ if (done) {
123
+ value = undefined;
124
+ }
125
+ }
126
+ }
127
+
128
+ // The weird "as IteratorResult<Record>" is needed because of
129
+ // https://github.com/Microsoft/TypeScript/issues/11375 and
130
+ // https://github.com/Microsoft/TypeScript/issues/2983
131
+ return {
132
+ done,
133
+ value,
134
+ };
135
+ },
136
+ };
137
+ },
138
+ };
139
+ }
140
+ }
141
+ export default RecordStore;
@@ -0,0 +1,78 @@
1
+ import cmp from './cmp.js';
2
+ /**
3
+ * Classic binary search implementation. Returns the index where the key
4
+ * should be inserted, assuming the records list is ordered.
5
+ */
6
+ function binarySearch(records, key) {
7
+ let low = 0;
8
+ let high = records.length;
9
+ let mid;
10
+ while (low < high) {
11
+ mid = (low + high) >>> 1; // like Math.floor((low + high) / 2) but fast
12
+ if (cmp(records[mid].key, key) < 0) {
13
+ low = mid + 1;
14
+ } else {
15
+ high = mid;
16
+ }
17
+ }
18
+ return low;
19
+ }
20
+
21
+ /**
22
+ * Equivalent to `records.findIndex(record => cmp(record.key, key) === 0)`
23
+ */
24
+ export function getIndexByKey(records, key) {
25
+ const idx = binarySearch(records, key);
26
+ const record = records[idx];
27
+ if (record && cmp(record.key, key) === 0) {
28
+ return idx;
29
+ }
30
+ return -1;
31
+ }
32
+
33
+ /**
34
+ * Equivalent to `records.find(record => cmp(record.key, key) === 0)`
35
+ */
36
+ export function getByKey(records, key) {
37
+ const idx = getIndexByKey(records, key);
38
+ return records[idx];
39
+ }
40
+
41
+ /**
42
+ * Equivalent to `records.findIndex(record => key.includes(record.key))`
43
+ */
44
+ export function getIndexByKeyRange(records, keyRange) {
45
+ const lowerIdx =
46
+ typeof keyRange.lower === 'undefined' ? 0 : binarySearch(records, keyRange.lower);
47
+ const upperIdx =
48
+ typeof keyRange.upper === 'undefined'
49
+ ? records.length - 1
50
+ : binarySearch(records, keyRange.upper);
51
+ for (let i = lowerIdx; i <= upperIdx; i++) {
52
+ const record = records[i];
53
+ if (record && keyRange.includes(record.key)) {
54
+ return i;
55
+ }
56
+ }
57
+ return -1;
58
+ }
59
+
60
+ /**
61
+ * Equivalent to `records.find(record => key.includes(record.key))`
62
+ */
63
+ export function getByKeyRange(records, keyRange) {
64
+ const idx = getIndexByKeyRange(records, keyRange);
65
+ return records[idx];
66
+ }
67
+
68
+ /**
69
+ * Equivalent to `records.findIndex(record => cmp(record.key, key) >= 0)`
70
+ */
71
+ export function getIndexByKeyGTE(records, key) {
72
+ const idx = binarySearch(records, key);
73
+ const record = records[idx];
74
+ if (record && cmp(record.key, key) >= 0) {
75
+ return idx;
76
+ }
77
+ return -1;
78
+ }
@@ -0,0 +1,25 @@
1
+ // http://w3c.github.io/IndexedDB/#check-that-a-key-could-be-injected-into-a-value
2
+ const canInjectKey = (keyPath, value) => {
3
+ if (Array.isArray(keyPath)) {
4
+ throw new Error(
5
+ 'The key paths used in this section are always strings and never sequences, since it is not possible to create a object store which has a key generator and also has a key path that is a sequence.',
6
+ );
7
+ }
8
+ const identifiers = keyPath.split('.');
9
+ if (identifiers.length === 0) {
10
+ throw new Error('Assert: identifiers is not empty');
11
+ }
12
+ identifiers.pop();
13
+ for (const identifier of identifiers) {
14
+ if (typeof value !== 'object' && !Array.isArray(value)) {
15
+ return false;
16
+ }
17
+ const hop = Object.hasOwn(value, identifier);
18
+ if (!hop) {
19
+ return true;
20
+ }
21
+ value = value[identifier];
22
+ }
23
+ return typeof value === 'object' || Array.isArray(value);
24
+ };
25
+ export default canInjectKey;
@@ -0,0 +1,77 @@
1
+ import { DataError } from './errors.js';
2
+ import valueToKey from './valueToKey.js';
3
+ const getType = x => {
4
+ if (typeof x === 'number') {
5
+ return 'Number';
6
+ }
7
+ if (Object.prototype.toString.call(x) === '[object Date]') {
8
+ return 'Date';
9
+ }
10
+ if (Array.isArray(x)) {
11
+ return 'Array';
12
+ }
13
+ if (typeof x === 'string') {
14
+ return 'String';
15
+ }
16
+ if (x instanceof ArrayBuffer) {
17
+ return 'Binary';
18
+ }
19
+ throw new DataError();
20
+ };
21
+
22
+ // https://w3c.github.io/IndexedDB/#compare-two-keys
23
+ const cmp = (first, second) => {
24
+ if (second === undefined) {
25
+ throw new TypeError();
26
+ }
27
+ first = valueToKey(first);
28
+ second = valueToKey(second);
29
+ const t1 = getType(first);
30
+ const t2 = getType(second);
31
+ if (t1 !== t2) {
32
+ if (t1 === 'Array') {
33
+ return 1;
34
+ }
35
+ if (t1 === 'Binary' && (t2 === 'String' || t2 === 'Date' || t2 === 'Number')) {
36
+ return 1;
37
+ }
38
+ if (t1 === 'String' && (t2 === 'Date' || t2 === 'Number')) {
39
+ return 1;
40
+ }
41
+ if (t1 === 'Date' && t2 === 'Number') {
42
+ return 1;
43
+ }
44
+ return -1;
45
+ }
46
+ if (t1 === 'Binary') {
47
+ first = new Uint8Array(first);
48
+ second = new Uint8Array(second);
49
+ }
50
+ if (t1 === 'Array' || t1 === 'Binary') {
51
+ const length = Math.min(first.length, second.length);
52
+ for (let i = 0; i < length; i++) {
53
+ const result = cmp(first[i], second[i]);
54
+ if (result !== 0) {
55
+ return result;
56
+ }
57
+ }
58
+ if (first.length > second.length) {
59
+ return 1;
60
+ }
61
+ if (first.length < second.length) {
62
+ return -1;
63
+ }
64
+ return 0;
65
+ }
66
+ if (t1 === 'Date') {
67
+ if (first.getTime() === second.getTime()) {
68
+ return 0;
69
+ }
70
+ } else {
71
+ if (first === second) {
72
+ return 0;
73
+ }
74
+ }
75
+ return first > second ? 1 : -1;
76
+ };
77
+ export default cmp;
@@ -0,0 +1,13 @@
1
+ // https://heycam.github.io/webidl/#EnforceRange
2
+
3
+ const enforceRange = (num, type) => {
4
+ const min = 0;
5
+ const max = type === 'unsigned long' ? 4294967295 : 9007199254740991;
6
+ if (isNaN(num) || num < min || num > max) {
7
+ throw new TypeError();
8
+ }
9
+ if (num >= 0) {
10
+ return Math.floor(num);
11
+ }
12
+ };
13
+ export default enforceRange;
@@ -0,0 +1,69 @@
1
+ const messages = {
2
+ AbortError: 'A request was aborted, for example through a call to IDBTransaction.abort.',
3
+ ConstraintError:
4
+ 'A mutation operation in the transaction failed because a constraint was not satisfied. For example, an object such as an object store or index already exists and a request attempted to create a new one.',
5
+ DataCloneError:
6
+ 'The data being stored could not be cloned by the internal structured cloning algorithm.',
7
+ DataError: 'Data provided to an operation does not meet requirements.',
8
+ InvalidAccessError:
9
+ 'An invalid operation was performed on an object. For example transaction creation attempt was made, but an empty scope was provided.',
10
+ InvalidStateError:
11
+ 'An operation was called on an object on which it is not allowed or at a time when it is not allowed. Also occurs if a request is made on a source object that has been deleted or removed. Use TransactionInactiveError or ReadOnlyError when possible, as they are more specific variations of InvalidStateError.',
12
+ NotFoundError:
13
+ 'The operation failed because the requested database object could not be found. For example, an object store did not exist but was being opened.',
14
+ ReadOnlyError: 'The mutating operation was attempted in a "readonly" transaction.',
15
+ TransactionInactiveError:
16
+ 'A request was placed against a transaction which is currently not active, or which is finished.',
17
+ VersionError:
18
+ 'An attempt was made to open a database using a lower version than the existing version.',
19
+ };
20
+ export class AbortError extends DOMException {
21
+ constructor(message = messages.AbortError) {
22
+ super(message, 'AbortError');
23
+ }
24
+ }
25
+ export class ConstraintError extends DOMException {
26
+ constructor(message = messages.ConstraintError) {
27
+ super(message, 'ConstraintError');
28
+ }
29
+ }
30
+ export class DataCloneError extends DOMException {
31
+ constructor(message = messages.DataCloneError) {
32
+ super(message, 'DataCloneError');
33
+ }
34
+ }
35
+ export class DataError extends DOMException {
36
+ constructor(message = messages.DataError) {
37
+ super(message, 'DataError');
38
+ }
39
+ }
40
+ export class InvalidAccessError extends DOMException {
41
+ constructor(message = messages.InvalidAccessError) {
42
+ super(message, 'InvalidAccessError');
43
+ }
44
+ }
45
+ export class InvalidStateError extends DOMException {
46
+ constructor(message = messages.InvalidStateError) {
47
+ super(message, 'InvalidStateError');
48
+ }
49
+ }
50
+ export class NotFoundError extends DOMException {
51
+ constructor(message = messages.NotFoundError) {
52
+ super(message, 'NotFoundError');
53
+ }
54
+ }
55
+ export class ReadOnlyError extends DOMException {
56
+ constructor(message = messages.ReadOnlyError) {
57
+ super(message, 'ReadOnlyError');
58
+ }
59
+ }
60
+ export class TransactionInactiveError extends DOMException {
61
+ constructor(message = messages.TransactionInactiveError) {
62
+ super(message, 'TransactionInactiveError');
63
+ }
64
+ }
65
+ export class VersionError extends DOMException {
66
+ constructor(message = messages.VersionError) {
67
+ super(message, 'VersionError');
68
+ }
69
+ }
@@ -0,0 +1,39 @@
1
+ import valueToKey from './valueToKey.js';
2
+
3
+ // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-for-extracting-a-key-from-a-value-using-a-key-path
4
+ const extractKey = (keyPath, value) => {
5
+ if (Array.isArray(keyPath)) {
6
+ const result = [];
7
+ for (let item of keyPath) {
8
+ // This doesn't make sense to me based on the spec, but it is needed to pass the W3C KeyPath tests (see same
9
+ // comment in validateKeyPath)
10
+ if (item !== undefined && item !== null && typeof item !== 'string' && item.toString) {
11
+ item = item.toString();
12
+ }
13
+ result.push(valueToKey(extractKey(item, value)));
14
+ }
15
+ return result;
16
+ }
17
+ if (keyPath === '') {
18
+ return value;
19
+ }
20
+ let remainingKeyPath = keyPath;
21
+ let object = value;
22
+ while (remainingKeyPath !== null) {
23
+ let identifier;
24
+ const i = remainingKeyPath.indexOf('.');
25
+ if (i >= 0) {
26
+ identifier = remainingKeyPath.slice(0, i);
27
+ remainingKeyPath = remainingKeyPath.slice(i + 1);
28
+ } else {
29
+ identifier = remainingKeyPath;
30
+ remainingKeyPath = null;
31
+ }
32
+ if (object === undefined || object === null || !Object.hasOwn(object, identifier)) {
33
+ return;
34
+ }
35
+ object = object[identifier];
36
+ }
37
+ return object;
38
+ };
39
+ export default extractKey;
@@ -0,0 +1,30 @@
1
+ // When running within Node.js (including jsdom), we want to use setImmediate
2
+ // (which runs immediately) rather than setTimeout (which enforces a minimum
3
+ // delay of 1ms, and on Windows only has a resolution of 15ms or so). jsdom
4
+ // doesn't provide setImmediate (to better match the browser environment) and
5
+ // sandboxes scripts, but its sandbox is by necessity imperfect, so we can break
6
+ // out of it:
7
+ //
8
+ // - https://github.com/jsdom/jsdom#executing-scripts
9
+ // - https://github.com/jsdom/jsdom/issues/2729
10
+ // - https://github.com/scala-js/scala-js-macrotask-executor/pull/17
11
+ function getSetImmediateFromJsdom() {
12
+ if (typeof navigator !== 'undefined' && /jsdom/.test(navigator.userAgent)) {
13
+ const outerRealmFunctionConstructor = Node.constructor;
14
+ return new outerRealmFunctionConstructor('return setImmediate')();
15
+ } else {
16
+ return undefined;
17
+ }
18
+ }
19
+
20
+ // Schedules a task to run later. Use Node.js's setImmediate if available and
21
+ // setTimeout otherwise. Note that options like process.nextTick or
22
+ // queueMicrotask will likely not work: IndexedDB semantics require that
23
+ // transactions are marked as not active when the event loop runs. The next
24
+ // tick queue and microtask queue run within the current event loop macrotask,
25
+ // so they'd process database operations too quickly.
26
+ export const queueTask = fn => {
27
+ const setImmediate =
28
+ globalThis.setImmediate || getSetImmediateFromJsdom() || (fn => setTimeout(fn, 0));
29
+ setImmediate(fn);
30
+ };
@@ -0,0 +1 @@
1
+ export {};