indexeddbshim 16.1.0 → 17.1.0
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/README.md +65 -3
- package/badges/licenses-badge-dev.svg +1 -1
- package/badges/licenses-badge.svg +1 -1
- package/dist/CFG.d.ts +1 -0
- package/dist/CFG.d.ts.map +1 -1
- package/dist/DOMException.d.ts.map +1 -1
- package/dist/DOMStringList.d.ts.map +1 -1
- package/dist/IDBCursor.d.ts +12 -3
- package/dist/IDBCursor.d.ts.map +1 -1
- package/dist/IDBDatabase.d.ts +2 -1
- package/dist/IDBDatabase.d.ts.map +1 -1
- package/dist/IDBFactory.d.ts +2 -1
- package/dist/IDBFactory.d.ts.map +1 -1
- package/dist/IDBIndex.d.ts +2 -1
- package/dist/IDBIndex.d.ts.map +1 -1
- package/dist/IDBKeyRange.d.ts +1 -1
- package/dist/IDBKeyRange.d.ts.map +1 -1
- package/dist/IDBObjectStore.d.ts +2 -1
- package/dist/IDBObjectStore.d.ts.map +1 -1
- package/dist/IDBRequest.d.ts +5 -3
- package/dist/IDBRequest.d.ts.map +1 -1
- package/dist/IDBTransaction.d.ts +23 -1
- package/dist/IDBTransaction.d.ts.map +1 -1
- package/dist/Key.d.ts.map +1 -1
- package/dist/Sca.d.ts.map +1 -1
- package/dist/UnicodeIdentifiers.d.ts.map +1 -1
- package/dist/browser-noninvasive.d.ts.map +1 -1
- package/dist/indexeddbshim-Key.js +1863 -1669
- package/dist/indexeddbshim-Key.js.map +1 -1
- package/dist/indexeddbshim-Key.min.js +2 -2
- package/dist/indexeddbshim-Key.min.js.map +1 -1
- package/dist/indexeddbshim-UnicodeIdentifiers-node.cjs +2373 -1893
- package/dist/indexeddbshim-UnicodeIdentifiers-node.cjs.map +1 -1
- package/dist/indexeddbshim-UnicodeIdentifiers.js +3124 -2285
- package/dist/indexeddbshim-UnicodeIdentifiers.js.map +1 -1
- package/dist/indexeddbshim-UnicodeIdentifiers.min.js +9 -2
- package/dist/indexeddbshim-UnicodeIdentifiers.min.js.map +1 -1
- package/dist/indexeddbshim-node.cjs +2373 -1893
- package/dist/indexeddbshim-node.cjs.map +1 -1
- package/dist/indexeddbshim-noninvasive.js +3123 -2284
- package/dist/indexeddbshim-noninvasive.js.map +1 -1
- package/dist/indexeddbshim-noninvasive.min.js +9 -2
- package/dist/indexeddbshim-noninvasive.min.js.map +1 -1
- package/dist/indexeddbshim.js +3120 -2282
- package/dist/indexeddbshim.js.map +1 -1
- package/dist/indexeddbshim.min.js +9 -2
- package/dist/indexeddbshim.min.js.map +1 -1
- package/dist/node-UnicodeIdentifiers.d.ts +2 -2
- package/dist/node-UnicodeIdentifiers.d.ts.map +1 -1
- package/dist/node.d.ts +2 -2
- package/dist/node.d.ts.map +1 -1
- package/dist/nodeSQLiteDatabase.d.ts +65 -0
- package/dist/nodeSQLiteDatabase.d.ts.map +1 -0
- package/dist/nodeWebSQL.d.ts.map +1 -1
- package/dist/util.d.ts +5 -0
- package/dist/util.d.ts.map +1 -1
- package/package.json +118 -106
- package/src/CFG.js +5 -3
- package/src/DOMException.js +11 -9
- package/src/DOMStringList.js +8 -3
- package/src/Event.js +2 -0
- package/src/IDBCursor.js +152 -95
- package/src/IDBDatabase.js +9 -6
- package/src/IDBFactory.js +31 -20
- package/src/IDBIndex.js +83 -79
- package/src/IDBKeyRange.js +42 -35
- package/src/IDBObjectStore.js +83 -77
- package/src/IDBRequest.js +28 -15
- package/src/IDBTransaction.js +40 -6
- package/src/IDBVersionChangeEvent.js +2 -0
- package/src/Key.js +28 -14
- package/src/Sca.js +2 -1
- package/src/UnicodeIdentifiers.js +2 -2
- package/src/browser-UnicodeIdentifiers.js +0 -1
- package/src/browser-noninvasive.js +0 -1
- package/src/browser.js +0 -1
- package/src/node-UnicodeIdentifiers.js +6 -2
- package/src/node.js +6 -2
- package/src/nodeSQLiteDatabase.js +174 -0
- package/src/nodeWebSQL.js +1 -3
- package/src/setGlobalVars.js +13 -13
- package/src/util.js +75 -15
package/src/IDBObjectStore.js
CHANGED
|
@@ -18,8 +18,9 @@ const readonlyProperties = ['keyPath', 'indexNames', 'transaction', 'autoIncreme
|
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* IndexedDB Object Store.
|
|
21
|
-
* @see
|
|
21
|
+
* @see https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBObjectStore
|
|
22
22
|
* @class
|
|
23
|
+
* @throws {TypeError}
|
|
23
24
|
*/
|
|
24
25
|
function IDBObjectStore () {
|
|
25
26
|
throw new TypeError('Illegal constructor');
|
|
@@ -85,89 +86,93 @@ IDBObjectStore.__createInstance = function (storeProperties, transaction) {
|
|
|
85
86
|
me.__indexNames = DOMStringList.__createInstance();
|
|
86
87
|
const {indexList} = storeProperties;
|
|
87
88
|
for (const indexName in indexList) {
|
|
88
|
-
if (Object.hasOwn(indexList, indexName)) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
89
|
+
if (!Object.hasOwn(indexList, indexName)) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const index = IDBIndex.__createInstance(me, indexList[indexName]);
|
|
94
|
+
me.__indexes[index.name] = index;
|
|
95
|
+
if (!index.__deleted) {
|
|
96
|
+
me.indexNames.push(index.name);
|
|
94
97
|
}
|
|
95
98
|
}
|
|
96
99
|
me.__oldIndexNames = me.indexNames.clone();
|
|
97
|
-
Object.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
});
|
|
102
|
-
Object.defineProperty(this, 'name', {
|
|
103
|
-
enumerable: false,
|
|
104
|
-
configurable: false,
|
|
105
|
-
/**
|
|
106
|
-
* @this {IDBObjectStoreFull}
|
|
107
|
-
* @returns {string}
|
|
108
|
-
*/
|
|
109
|
-
get () {
|
|
110
|
-
return this.__name;
|
|
111
|
-
},
|
|
112
|
-
/**
|
|
113
|
-
* @param {string} name
|
|
114
|
-
* @this {IDBObjectStoreFull}
|
|
115
|
-
* @returns {void}
|
|
116
|
-
*/
|
|
117
|
-
set (name) {
|
|
118
|
-
const me = this;
|
|
119
|
-
name = util.convertToDOMString(name);
|
|
120
|
-
const oldName = me.name;
|
|
121
|
-
IDBObjectStoreAlias.__invalidStateIfDeleted(me);
|
|
122
|
-
IDBTransaction.__assertVersionChange(me.transaction);
|
|
123
|
-
IDBTransaction.__assertActive(me.transaction);
|
|
124
|
-
if (oldName === name) {
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
if (me.__idbdb.__objectStores[name] && !me.__idbdb.__objectStores[name].__pendingDelete) {
|
|
128
|
-
throw createDOMException('ConstraintError', 'Object store "' + name + '" already exists in ' + me.__idbdb.name);
|
|
100
|
+
Object.defineProperties(this, {
|
|
101
|
+
__currentName: {
|
|
102
|
+
get () {
|
|
103
|
+
return '__pendingName' in this ? this.__pendingName : this.name;
|
|
129
104
|
}
|
|
105
|
+
},
|
|
106
|
+
name: {
|
|
107
|
+
enumerable: false,
|
|
108
|
+
configurable: false,
|
|
109
|
+
/**
|
|
110
|
+
* @this {IDBObjectStoreFull}
|
|
111
|
+
* @returns {string}
|
|
112
|
+
*/
|
|
113
|
+
get () {
|
|
114
|
+
return this.__name;
|
|
115
|
+
},
|
|
116
|
+
/**
|
|
117
|
+
* @param {string} name
|
|
118
|
+
* @this {IDBObjectStoreFull}
|
|
119
|
+
* @returns {void}
|
|
120
|
+
*/
|
|
121
|
+
set (name) {
|
|
122
|
+
const me = this;
|
|
123
|
+
name = util.convertToDOMString(name);
|
|
124
|
+
const oldName = me.name;
|
|
125
|
+
IDBObjectStoreAlias.__invalidStateIfDeleted(me);
|
|
126
|
+
IDBTransaction.__assertVersionChange(me.transaction);
|
|
127
|
+
IDBTransaction.__assertActive(me.transaction);
|
|
128
|
+
if (oldName === name) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (Object.hasOwn(me.__idbdb.__objectStores, name) && !me.__idbdb.__objectStores[name].__pendingDelete) {
|
|
132
|
+
throw createDOMException('ConstraintError', 'Object store "' + name + '" already exists in ' + me.__idbdb.name);
|
|
133
|
+
}
|
|
130
134
|
|
|
131
|
-
|
|
135
|
+
me.__name = name;
|
|
132
136
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
+
const oldStore = me.__idbdb.__objectStores[oldName];
|
|
138
|
+
oldStore.__name = name; // Fix old references
|
|
139
|
+
me.__idbdb.__objectStores[name] = oldStore; // Ensure new reference accessible
|
|
140
|
+
delete me.__idbdb.__objectStores[oldName]; // Ensure won't be found
|
|
137
141
|
|
|
138
|
-
|
|
142
|
+
me.__idbdb.objectStoreNames.splice(me.__idbdb.objectStoreNames.indexOf(oldName), 1, name);
|
|
139
143
|
|
|
140
|
-
|
|
144
|
+
const oldHandle = /** @type {IDBObjectStoreFull} */ (
|
|
145
|
+
/** @type {import('./IDBTransaction.js').IDBTransactionFull} */ (
|
|
146
|
+
me.transaction
|
|
147
|
+
).__storeHandles[oldName]
|
|
148
|
+
);
|
|
149
|
+
oldHandle.__name = name; // Fix old references
|
|
141
150
|
/** @type {import('./IDBTransaction.js').IDBTransactionFull} */ (
|
|
142
151
|
me.transaction
|
|
143
|
-
).__storeHandles[
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
success();
|
|
152
|
+
).__storeHandles[name] = oldHandle; // Ensure new reference accessible
|
|
153
|
+
|
|
154
|
+
me.__pendingName = oldName;
|
|
155
|
+
|
|
156
|
+
const sql = 'UPDATE __sys__ SET "name" = ? WHERE "name" = ?';
|
|
157
|
+
const sqlValues = [util.escapeSQLiteStatement(name), util.escapeSQLiteStatement(oldName)];
|
|
158
|
+
if (CFG.DEBUG) { console.log(sql, sqlValues); }
|
|
159
|
+
/** @type {import('./IDBTransaction.js').IDBTransactionFull} */ (
|
|
160
|
+
me.transaction
|
|
161
|
+
).__addNonRequestToTransactionQueue(function objectStoreClear (tx, args, success, error) {
|
|
162
|
+
tx.executeSql(sql, sqlValues, function (tx) {
|
|
163
|
+
// This SQL preserves indexes per https://www.sqlite.org/lang_altertable.html
|
|
164
|
+
const sql = 'ALTER TABLE ' + util.escapeStoreNameForSQL(oldName) + ' RENAME TO ' + util.escapeStoreNameForSQL(name);
|
|
165
|
+
if (CFG.DEBUG) { console.log(sql); }
|
|
166
|
+
tx.executeSql(sql, [], function () {
|
|
167
|
+
delete me.__pendingName;
|
|
168
|
+
success();
|
|
169
|
+
});
|
|
170
|
+
}, function (tx, err) {
|
|
171
|
+
error(err);
|
|
172
|
+
return false;
|
|
165
173
|
});
|
|
166
|
-
}, function (tx, err) {
|
|
167
|
-
error(err);
|
|
168
|
-
return false;
|
|
169
174
|
});
|
|
170
|
-
}
|
|
175
|
+
}
|
|
171
176
|
}
|
|
172
177
|
});
|
|
173
178
|
}
|
|
@@ -239,7 +244,7 @@ IDBObjectStore.__createObjectStore = function (db, store) {
|
|
|
239
244
|
);
|
|
240
245
|
|
|
241
246
|
const storeHandles = transaction.__storeHandles;
|
|
242
|
-
if (!storeHandles
|
|
247
|
+
if (!Object.hasOwn(storeHandles, storeName) ||
|
|
243
248
|
// These latter conditions are to allow store
|
|
244
249
|
// recreation to create new clone object
|
|
245
250
|
storeHandles[storeName].__pendingDelete ||
|
|
@@ -609,7 +614,6 @@ IDBObjectStore.prototype.__insertData = function (tx, encoded, value, clonedKeyO
|
|
|
609
614
|
return false;
|
|
610
615
|
});
|
|
611
616
|
return undefined;
|
|
612
|
-
// eslint-disable-next-line sonarjs/no-invariant-returns -- Convenient
|
|
613
617
|
}).catch(function (err) {
|
|
614
618
|
/**
|
|
615
619
|
* @returns {void}
|
|
@@ -1036,7 +1040,7 @@ IDBObjectStore.prototype.index = function (indexName) {
|
|
|
1036
1040
|
throw createDOMException('NotFoundError', 'Index "' + indexName + '" does not exist on ' + me.__currentName);
|
|
1037
1041
|
}
|
|
1038
1042
|
|
|
1039
|
-
if (!me.__indexHandles
|
|
1043
|
+
if (!Object.hasOwn(me.__indexHandles, indexName) ||
|
|
1040
1044
|
me.__indexes[indexName].__pendingDelete ||
|
|
1041
1045
|
me.__indexes[indexName].__deleted
|
|
1042
1046
|
) {
|
|
@@ -1069,7 +1073,7 @@ IDBObjectStore.prototype.createIndex = function (indexName, keyPath /* , optiona
|
|
|
1069
1073
|
IDBTransaction.__assertVersionChange(me.transaction);
|
|
1070
1074
|
IDBObjectStore.__invalidStateIfDeleted(me);
|
|
1071
1075
|
IDBTransaction.__assertActive(me.transaction);
|
|
1072
|
-
if (me.__indexes
|
|
1076
|
+
if (Object.hasOwn(me.__indexes, indexName) && !me.__indexes[indexName].__deleted && !me.__indexes[indexName].__pendingDelete) {
|
|
1073
1077
|
throw createDOMException('ConstraintError', 'Index "' + indexName + '" already exists on ' + me.__currentName);
|
|
1074
1078
|
}
|
|
1075
1079
|
|
|
@@ -1081,7 +1085,7 @@ IDBObjectStore.prototype.createIndex = function (indexName, keyPath /* , optiona
|
|
|
1081
1085
|
throw createDOMException('InvalidAccessError', 'The keyPath argument was an array and the multiEntry option is true.');
|
|
1082
1086
|
}
|
|
1083
1087
|
|
|
1084
|
-
optionalParameters
|
|
1088
|
+
optionalParameters ||= {};
|
|
1085
1089
|
/** @type {import('./IDBIndex.js').IDBIndexProperties} */
|
|
1086
1090
|
const indexProperties = {
|
|
1087
1091
|
columnName: indexName,
|
|
@@ -1121,6 +1125,7 @@ IDBObjectStore.prototype.deleteIndex = function (name) {
|
|
|
1121
1125
|
IDBIndex.__deleteIndex(me, index);
|
|
1122
1126
|
};
|
|
1123
1127
|
|
|
1128
|
+
/* eslint-disable unicorn/no-top-level-side-effects -- Would be good */
|
|
1124
1129
|
util.defineReadonlyOuterInterface(IDBObjectStore.prototype, readonlyProperties);
|
|
1125
1130
|
util.defineOuterInterface(IDBObjectStore.prototype, ['name']);
|
|
1126
1131
|
|
|
@@ -1129,5 +1134,6 @@ IDBObjectStore.prototype[Symbol.toStringTag] = 'IDBObjectStorePrototype';
|
|
|
1129
1134
|
Object.defineProperty(IDBObjectStore, 'prototype', {
|
|
1130
1135
|
writable: false
|
|
1131
1136
|
});
|
|
1137
|
+
/* eslint-enable unicorn/no-top-level-side-effects -- Would be good */
|
|
1132
1138
|
|
|
1133
1139
|
export default IDBObjectStore;
|
package/src/IDBRequest.js
CHANGED
|
@@ -8,8 +8,9 @@ const doneFlagGetters = ['result', 'error'];
|
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* The IDBRequest Object that is returns for all async calls.
|
|
11
|
-
* @see
|
|
11
|
+
* @see https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#request-api
|
|
12
12
|
* @class
|
|
13
|
+
* @throws {TypeError}
|
|
13
14
|
*/
|
|
14
15
|
function IDBRequest () {
|
|
15
16
|
throw new TypeError('Illegal constructor');
|
|
@@ -48,21 +49,26 @@ IDBRequest.__super = function IDBRequest () {
|
|
|
48
49
|
legacyOutputDidListenersThrowFlag: true // Event hook for IndexedB
|
|
49
50
|
});
|
|
50
51
|
doneFlagGetters.forEach((prop) => {
|
|
51
|
-
Object.
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
52
|
+
Object.defineProperties(
|
|
53
|
+
this,
|
|
54
|
+
{
|
|
55
|
+
['__' + prop]: {
|
|
56
|
+
enumerable: false,
|
|
57
|
+
configurable: false,
|
|
58
|
+
writable: true
|
|
59
|
+
},
|
|
60
|
+
[prop]: {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
configurable: true,
|
|
63
|
+
get () {
|
|
64
|
+
if (!this.__done) {
|
|
65
|
+
throw createDOMException('InvalidStateError', "Can't get " + prop + '; the request is still pending.');
|
|
66
|
+
}
|
|
67
|
+
return this['__' + prop];
|
|
68
|
+
}
|
|
62
69
|
}
|
|
63
|
-
return this['__' + prop];
|
|
64
70
|
}
|
|
65
|
-
|
|
71
|
+
);
|
|
66
72
|
});
|
|
67
73
|
util.defineReadonlyProperties(this, readonlyProperties, {
|
|
68
74
|
readyState: {
|
|
@@ -106,6 +112,7 @@ IDBRequest.prototype.__getParent = function () {
|
|
|
106
112
|
return this.__transaction;
|
|
107
113
|
};
|
|
108
114
|
|
|
115
|
+
/* eslint-disable unicorn/no-top-level-side-effects -- Would be good */
|
|
109
116
|
// Illegal invocations
|
|
110
117
|
util.defineReadonlyOuterInterface(IDBRequest.prototype, readonlyProperties);
|
|
111
118
|
util.defineReadonlyOuterInterface(IDBRequest.prototype, doneFlagGetters);
|
|
@@ -123,16 +130,18 @@ IDBRequest.__super.prototype = IDBRequest.prototype;
|
|
|
123
130
|
Object.defineProperty(IDBRequest, 'prototype', {
|
|
124
131
|
writable: false
|
|
125
132
|
});
|
|
133
|
+
/* eslint-enable unicorn/no-top-level-side-effects -- Would be good */
|
|
126
134
|
|
|
127
135
|
const openListeners = ['onblocked', 'onupgradeneeded'];
|
|
128
136
|
|
|
129
137
|
/**
|
|
130
|
-
* @typedef {IDBRequestFull & IDBOpenDBRequest
|
|
138
|
+
* @typedef {IDBRequestFull & IDBOpenDBRequest} IDBOpenDBRequestFull
|
|
131
139
|
*/
|
|
132
140
|
|
|
133
141
|
/**
|
|
134
142
|
* The IDBOpenDBRequest called when a database is opened.
|
|
135
143
|
* @class
|
|
144
|
+
* @throws {TypeError}
|
|
136
145
|
*/
|
|
137
146
|
function IDBOpenDBRequest () {
|
|
138
147
|
throw new TypeError('Illegal constructor');
|
|
@@ -141,12 +150,14 @@ function IDBOpenDBRequest () {
|
|
|
141
150
|
// @ts-expect-error It's ok
|
|
142
151
|
IDBOpenDBRequest.prototype = Object.create(IDBRequest.prototype);
|
|
143
152
|
|
|
153
|
+
/* eslint-disable unicorn/no-top-level-side-effects -- Would be good */
|
|
144
154
|
Object.defineProperty(IDBOpenDBRequest.prototype, 'constructor', {
|
|
145
155
|
enumerable: false,
|
|
146
156
|
writable: true,
|
|
147
157
|
configurable: true,
|
|
148
158
|
value: IDBOpenDBRequest
|
|
149
159
|
});
|
|
160
|
+
/* eslint-enable unicorn/no-top-level-side-effects -- Would be good */
|
|
150
161
|
|
|
151
162
|
const IDBOpenDBRequestAlias = IDBOpenDBRequest;
|
|
152
163
|
/**
|
|
@@ -175,6 +186,7 @@ IDBOpenDBRequest.__createInstance = function () {
|
|
|
175
186
|
return new IDBOpenDBRequest();
|
|
176
187
|
};
|
|
177
188
|
|
|
189
|
+
/* eslint-disable unicorn/no-top-level-side-effects -- Would be good */
|
|
178
190
|
util.defineOuterInterface(IDBOpenDBRequest.prototype, openListeners);
|
|
179
191
|
|
|
180
192
|
IDBOpenDBRequest.prototype[Symbol.toStringTag] = 'IDBOpenDBRequestPrototype';
|
|
@@ -182,5 +194,6 @@ IDBOpenDBRequest.prototype[Symbol.toStringTag] = 'IDBOpenDBRequestPrototype';
|
|
|
182
194
|
Object.defineProperty(IDBOpenDBRequest, 'prototype', {
|
|
183
195
|
writable: false
|
|
184
196
|
});
|
|
197
|
+
/* eslint-enable unicorn/no-top-level-side-effects -- Would be good */
|
|
185
198
|
|
|
186
199
|
export {IDBRequest, IDBOpenDBRequest};
|
package/src/IDBTransaction.js
CHANGED
|
@@ -50,6 +50,7 @@ const readonlyProperties = ['objectStoreNames', 'mode', 'db', 'error'];
|
|
|
50
50
|
* },
|
|
51
51
|
* __requestsFinished: boolean,
|
|
52
52
|
* __transFinishedCb: (err: boolean, cb: ((bool?: boolean) => void)) => void,
|
|
53
|
+
* __callTransFinishedCb: (err: boolean, cb: ((bool?: boolean) => void)) => void,
|
|
53
54
|
* __transactionEndCallback: () => void,
|
|
54
55
|
* __transactionFinished: boolean,
|
|
55
56
|
* __completed: boolean,
|
|
@@ -85,8 +86,9 @@ const readonlyProperties = ['objectStoreNames', 'mode', 'db', 'error'];
|
|
|
85
86
|
|
|
86
87
|
/**
|
|
87
88
|
* The IndexedDB Transaction.
|
|
88
|
-
* @see
|
|
89
|
+
* @see https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBTransaction
|
|
89
90
|
* @class
|
|
91
|
+
* @throws {TypeError}
|
|
90
92
|
*/
|
|
91
93
|
function IDBTransaction () {
|
|
92
94
|
throw new TypeError('Illegal constructor');
|
|
@@ -108,6 +110,7 @@ IDBTransaction.__createInstance = function (db, storeNames, mode) {
|
|
|
108
110
|
// @ts-expect-error It's ok
|
|
109
111
|
me[Symbol.toStringTag] = 'IDBTransaction';
|
|
110
112
|
util.defineReadonlyProperties(me, readonlyProperties);
|
|
113
|
+
// eslint-disable-next-line unicorn/no-top-level-assignment-in-function -- Debugging only
|
|
111
114
|
me.__id = ++uniqueID; // for debugging simultaneous transactions
|
|
112
115
|
me.__active = true;
|
|
113
116
|
me.__running = false;
|
|
@@ -155,6 +158,35 @@ IDBTransaction.prototype = EventTargetFactory.createInstance({
|
|
|
155
158
|
IDBTransaction.prototype.__transFinishedCb = function (err, cb) {
|
|
156
159
|
cb(Boolean(err));
|
|
157
160
|
};
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* In Node, the real (SQL-commit-capable) `__transFinishedCb` is only
|
|
164
|
+
* installed once the underlying WebSQL driver's own SQL-queue-idle check
|
|
165
|
+
* has fired at least once for this transaction (asynchronously, via the
|
|
166
|
+
* `nonstandardTransCb` passed to `db.transaction`/`.readTransaction`).
|
|
167
|
+
* Since our own request processing can now finish synchronously (e.g., a
|
|
168
|
+
* trivial upgrade using a synchronous SQL driver), it is possible to reach
|
|
169
|
+
* transaction completion here before that has happened, in which case
|
|
170
|
+
* `__transFinishedCb` is still the non-committing default above. Calling
|
|
171
|
+
* that default directly would silently skip the actual SQL commit and
|
|
172
|
+
* leave the underlying WebSQL transaction "running" forever, hanging any
|
|
173
|
+
* later transaction on that same database connection. So, if the real
|
|
174
|
+
* callback isn't installed yet, defer and retry until it is.
|
|
175
|
+
* @this {IDBTransactionFull}
|
|
176
|
+
* @param {boolean} err
|
|
177
|
+
* @param {(bool?: boolean) => void} cb
|
|
178
|
+
* @returns {void}
|
|
179
|
+
*/
|
|
180
|
+
IDBTransaction.prototype.__callTransFinishedCb = function (err, cb) {
|
|
181
|
+
const me = this;
|
|
182
|
+
if (me.__transFinishedCb === IDBTransaction.prototype.__transFinishedCb) {
|
|
183
|
+
setTimeout(() => {
|
|
184
|
+
me.__callTransFinishedCb(err, cb);
|
|
185
|
+
}, 0);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
me.__transFinishedCb(err, cb);
|
|
189
|
+
};
|
|
158
190
|
/**
|
|
159
191
|
* @this {IDBTransactionFull}
|
|
160
192
|
* @returns {void}
|
|
@@ -212,7 +244,7 @@ IDBTransaction.prototype.__executeRequests = function () {
|
|
|
212
244
|
me.__abortTransaction(createDOMException('AbortError', 'A request was aborted (in user handler after success).'));
|
|
213
245
|
return;
|
|
214
246
|
}
|
|
215
|
-
executeNextRequest
|
|
247
|
+
util.runContinuationSafely(executeNextRequest);
|
|
216
248
|
}
|
|
217
249
|
|
|
218
250
|
/**
|
|
@@ -280,7 +312,7 @@ IDBTransaction.prototype.__executeRequests = function () {
|
|
|
280
312
|
try {
|
|
281
313
|
q = me.__requests[i];
|
|
282
314
|
if (!q.req) {
|
|
283
|
-
q.op(tx, q.args, executeNextRequest, error);
|
|
315
|
+
q.op(tx, q.args, () => util.runContinuationSafely(executeNextRequest), error);
|
|
284
316
|
return;
|
|
285
317
|
}
|
|
286
318
|
if (q.req.__done) { // Avoid continuing with aborted requests
|
|
@@ -509,7 +541,7 @@ IDBTransaction.prototype.objectStore = function (objectStoreName) {
|
|
|
509
541
|
throw createDOMException('NotFoundError', objectStoreName + ' does not exist in ' + me.db.name);
|
|
510
542
|
}
|
|
511
543
|
|
|
512
|
-
if (!me.__storeHandles
|
|
544
|
+
if (!Object.hasOwn(me.__storeHandles, objectStoreName) ||
|
|
513
545
|
// These latter conditions are to allow store
|
|
514
546
|
// recreation to create new clone object
|
|
515
547
|
me.__storeHandles[objectStoreName].__pendingDelete ||
|
|
@@ -615,7 +647,7 @@ IDBTransaction.prototype.__abortTransaction = function (err) {
|
|
|
615
647
|
}
|
|
616
648
|
q.req.dispatchEvent(reqEvt); // No need to catch errors
|
|
617
649
|
resolve();
|
|
618
|
-
});
|
|
650
|
+
}, 0);
|
|
619
651
|
}
|
|
620
652
|
);
|
|
621
653
|
});
|
|
@@ -626,7 +658,7 @@ IDBTransaction.prototype.__abortTransaction = function (err) {
|
|
|
626
658
|
me.dispatchEvent(evt);
|
|
627
659
|
me.__storeHandles = {};
|
|
628
660
|
me.dispatchEvent(createEvent('__abort'));
|
|
629
|
-
});
|
|
661
|
+
}, 0);
|
|
630
662
|
return undefined;
|
|
631
663
|
}).catch((err) => {
|
|
632
664
|
console.log('Abort error');
|
|
@@ -752,6 +784,7 @@ IDBTransaction.prototype.__getParent = function () {
|
|
|
752
784
|
return this.db;
|
|
753
785
|
};
|
|
754
786
|
|
|
787
|
+
/* eslint-disable unicorn/no-top-level-side-effects -- Would be good */
|
|
755
788
|
util.defineOuterInterface(IDBTransaction.prototype, listeners);
|
|
756
789
|
util.defineReadonlyOuterInterface(IDBTransaction.prototype, readonlyProperties);
|
|
757
790
|
|
|
@@ -765,5 +798,6 @@ Object.defineProperty(IDBTransaction.prototype, 'constructor', {
|
|
|
765
798
|
Object.defineProperty(IDBTransaction, 'prototype', {
|
|
766
799
|
writable: false
|
|
767
800
|
});
|
|
801
|
+
/* eslint-enable unicorn/no-top-level-side-effects -- Would be good */
|
|
768
802
|
|
|
769
803
|
export default IDBTransaction;
|
|
@@ -29,6 +29,7 @@ IDBVersionChangeEvent.prototype[Symbol.toStringTag] = 'IDBVersionChangeEventProt
|
|
|
29
29
|
* @typedef {number} Integer
|
|
30
30
|
*/
|
|
31
31
|
|
|
32
|
+
/* eslint-disable unicorn/no-top-level-side-effects -- Would be good */
|
|
32
33
|
readonlyProperties.forEach((prop) => {
|
|
33
34
|
// Ensure for proper interface testing that "get <name>" is the function name
|
|
34
35
|
const o = {
|
|
@@ -73,5 +74,6 @@ Object.defineProperty(IDBVersionChangeEvent.prototype, 'constructor', {
|
|
|
73
74
|
Object.defineProperty(IDBVersionChangeEvent, 'prototype', {
|
|
74
75
|
writable: false
|
|
75
76
|
});
|
|
77
|
+
/* eslint-enable unicorn/no-top-level-side-effects -- Would be good */
|
|
76
78
|
|
|
77
79
|
export default IDBVersionChangeEvent;
|
package/src/Key.js
CHANGED
|
@@ -64,12 +64,15 @@ const keyTypeToEncodedChar = {
|
|
|
64
64
|
binary: 500,
|
|
65
65
|
array: 600
|
|
66
66
|
};
|
|
67
|
+
|
|
68
|
+
/* eslint-disable unicorn/no-top-level-side-effects -- Would be good */
|
|
67
69
|
const keyTypes = /** @type {(KeyType|"invalid")[]} */ (Object.keys(keyTypeToEncodedChar));
|
|
68
70
|
keyTypes.forEach((k) => {
|
|
69
71
|
keyTypeToEncodedChar[k] = String.fromCodePoint(
|
|
70
72
|
/** @type {number} */ (keyTypeToEncodedChar[k])
|
|
71
73
|
);
|
|
72
74
|
});
|
|
75
|
+
/* eslint-enable unicorn/no-top-level-side-effects -- Would be good */
|
|
73
76
|
|
|
74
77
|
const encodedCharToKeyType = keyTypes.reduce((o, k) => {
|
|
75
78
|
o[keyTypeToEncodedChar[k]] = k;
|
|
@@ -160,15 +163,14 @@ const types = {
|
|
|
160
163
|
if (key > -1) {
|
|
161
164
|
sign = signValues.indexOf('smallNegative');
|
|
162
165
|
exponent = padBase32Exponent(significantDigitIndex);
|
|
163
|
-
mantissa = flipBase32(padBase32Mantissa(key32));
|
|
164
166
|
// Non-negative exponent case:
|
|
165
167
|
} else {
|
|
166
168
|
sign = signValues.indexOf('bigNegative');
|
|
167
169
|
exponent = flipBase32(padBase32Exponent(
|
|
168
170
|
(decimalIndex !== -1) ? decimalIndex : key32.length
|
|
169
171
|
));
|
|
170
|
-
mantissa = flipBase32(padBase32Mantissa(key32));
|
|
171
172
|
}
|
|
173
|
+
mantissa = flipBase32(padBase32Mantissa(key32));
|
|
172
174
|
// Non-negative cases:
|
|
173
175
|
// Negative exponent case:
|
|
174
176
|
} else if (key < 1) {
|
|
@@ -208,9 +210,9 @@ const types = {
|
|
|
208
210
|
|
|
209
211
|
switch (signValues[sign]) {
|
|
210
212
|
case 'negativeInfinity':
|
|
211
|
-
return
|
|
213
|
+
return -Infinity;
|
|
212
214
|
case 'positiveInfinity':
|
|
213
|
-
return
|
|
215
|
+
return Infinity;
|
|
214
216
|
case 'bigPositive':
|
|
215
217
|
return pow32(mantissa, exponent);
|
|
216
218
|
case 'smallPositive':
|
|
@@ -281,14 +283,22 @@ const types = {
|
|
|
281
283
|
encoded[i] = encodedItem;
|
|
282
284
|
}
|
|
283
285
|
encoded.push(keyTypeToEncodedChar.invalid + '-'); // append an extra item, so empty arrays sort correctly
|
|
284
|
-
|
|
286
|
+
let encodedKey = JSON.stringify(encoded);
|
|
287
|
+
if (CFG.escapeNULForSQLiteStatements === false) {
|
|
288
|
+
encodedKey = encodedKey.replaceAll(String.raw`\u0000`, '\0');
|
|
289
|
+
}
|
|
290
|
+
return keyTypeToEncodedChar.array + '-' + encodedKey;
|
|
285
291
|
},
|
|
286
292
|
/**
|
|
287
293
|
* @param {string} key
|
|
288
294
|
* @returns {ValueTypeArray}
|
|
289
295
|
*/
|
|
290
296
|
decode (key) {
|
|
291
|
-
|
|
297
|
+
let decodedKey = key.slice(2);
|
|
298
|
+
if (CFG.escapeNULForSQLiteStatements === false) {
|
|
299
|
+
decodedKey = decodedKey.replaceAll('\0', String.raw`\u0000`);
|
|
300
|
+
}
|
|
301
|
+
const decoded = JSON.parse(decodedKey);
|
|
292
302
|
decoded.pop(); // remove the extra item
|
|
293
303
|
for (let i = 0; i < decoded.length; i++) {
|
|
294
304
|
const item = decoded[i];
|
|
@@ -336,7 +346,7 @@ const types = {
|
|
|
336
346
|
decode (key) {
|
|
337
347
|
// Set the entries in buffer's [[ArrayBufferData]] to those in `value`
|
|
338
348
|
const k = key.slice(2);
|
|
339
|
-
const arr = k.length ? k.split(',').map(
|
|
349
|
+
const arr = k.length ? k.split(',').map(Number) : [];
|
|
340
350
|
const buffer = new ArrayBuffer(arr.length);
|
|
341
351
|
const uint8 = new Uint8Array(buffer);
|
|
342
352
|
uint8.set(arr);
|
|
@@ -417,7 +427,7 @@ function pow32 (mantissa, exponent) {
|
|
|
417
427
|
* @returns {Float}
|
|
418
428
|
*/
|
|
419
429
|
function roundToPrecision (num, precision = 16) {
|
|
420
|
-
return Number
|
|
430
|
+
return Number(num.toPrecision(precision));
|
|
421
431
|
}
|
|
422
432
|
|
|
423
433
|
/**
|
|
@@ -481,7 +491,7 @@ function convertValueToMultiEntryKey (input) {
|
|
|
481
491
|
*/
|
|
482
492
|
function getCopyBytesHeldByBufferSource (O) {
|
|
483
493
|
let offset = 0;
|
|
484
|
-
let length
|
|
494
|
+
let length;
|
|
485
495
|
if (ArrayBuffer.isView(O)) { // Has [[ViewedArrayBuffer]] internal slot
|
|
486
496
|
const arrayBuffer = O.buffer;
|
|
487
497
|
if (arrayBuffer === undefined) {
|
|
@@ -518,7 +528,7 @@ function getCopyBytesHeldByBufferSource (O) {
|
|
|
518
528
|
* @returns {KeyValueObject}
|
|
519
529
|
*/
|
|
520
530
|
function convertValueToKeyValueDecoded (input, seen, multiEntry, fullKeys) {
|
|
521
|
-
seen
|
|
531
|
+
seen ||= [];
|
|
522
532
|
if (seen.includes(input)) {
|
|
523
533
|
return {
|
|
524
534
|
type: 'array',
|
|
@@ -868,7 +878,6 @@ function findMultiEntryMatches (keyEntry, range) {
|
|
|
868
878
|
continue;
|
|
869
879
|
}
|
|
870
880
|
if (key.length === 1) {
|
|
871
|
-
// eslint-disable-next-line sonarjs/updated-loop-counter -- Convenient
|
|
872
881
|
key = key[0];
|
|
873
882
|
} else {
|
|
874
883
|
const nested = findMultiEntryMatches(key, range);
|
|
@@ -1041,9 +1050,14 @@ function assignCurrentNumber (tx, store, num, successCb, failCb) {
|
|
|
1041
1050
|
* @returns {void}
|
|
1042
1051
|
*/
|
|
1043
1052
|
function setCurrentNumber (tx, store, num, successCb, failCb) {
|
|
1044
|
-
num = num === MAX_ALLOWED_CURRENT_NUMBER
|
|
1045
|
-
|
|
1046
|
-
|
|
1053
|
+
num = 1 + (num === MAX_ALLOWED_CURRENT_NUMBER
|
|
1054
|
+
// Since incrementing by one will have no effect in JavaScript on this
|
|
1055
|
+
// unsafe max, we represent the max as a number incremented by two.
|
|
1056
|
+
// The getting of the current number is never returned to the user and
|
|
1057
|
+
// is only used in safe comparisons, so it is safe for us to represent
|
|
1058
|
+
// it in this manner
|
|
1059
|
+
? num + 1
|
|
1060
|
+
: num);
|
|
1047
1061
|
return assignCurrentNumber(tx, store, num, successCb, failCb);
|
|
1048
1062
|
}
|
|
1049
1063
|
|
package/src/Sca.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
|
|
5
5
|
import {createDOMException, ShimDOMException} from './DOMException.js';
|
|
6
6
|
|
|
7
|
-
// See:
|
|
7
|
+
// See: https://stackoverflow.com/questions/42170826/categories-for-rejection-by-the-structured-cloning-algorithm
|
|
8
8
|
|
|
9
9
|
let typeson = new Typeson().register(structuredCloningThrowing);
|
|
10
10
|
|
|
@@ -14,6 +14,7 @@ let typeson = new Typeson().register(structuredCloningThrowing);
|
|
|
14
14
|
* @returns {void}
|
|
15
15
|
*/
|
|
16
16
|
function register (func) {
|
|
17
|
+
// eslint-disable-next-line unicorn/no-top-level-assignment-in-function -- Should be one-time cache
|
|
17
18
|
typeson = new Typeson().register(func(structuredCloningThrowing));
|
|
18
19
|
}
|
|
19
20
|
|