indexeddbshim 17.3.3 → 17.4.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 +3 -146
- package/dist/CFG.d.ts +1 -0
- package/dist/CFG.d.ts.map +1 -1
- package/dist/DOMException.d.ts +4 -4
- package/dist/DOMException.d.ts.map +1 -1
- package/dist/IDBFactory.d.ts.map +1 -1
- package/dist/IDBTransaction.d.ts +8 -6
- 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/indexeddbshim-Key.js +54 -14
- 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 +212 -80
- package/dist/indexeddbshim-UnicodeIdentifiers-node.cjs.map +1 -1
- package/dist/indexeddbshim-UnicodeIdentifiers.js +201 -79
- package/dist/indexeddbshim-UnicodeIdentifiers.js.map +1 -1
- package/dist/indexeddbshim-UnicodeIdentifiers.min.js +3 -3
- package/dist/indexeddbshim-UnicodeIdentifiers.min.js.map +1 -1
- package/dist/indexeddbshim-node.cjs +212 -80
- package/dist/indexeddbshim-node.cjs.map +1 -1
- package/dist/indexeddbshim-noninvasive.js +201 -79
- package/dist/indexeddbshim-noninvasive.js.map +1 -1
- package/dist/indexeddbshim-noninvasive.min.js +3 -3
- package/dist/indexeddbshim-noninvasive.min.js.map +1 -1
- package/dist/indexeddbshim.js +201 -79
- package/dist/indexeddbshim.js.map +1 -1
- package/dist/indexeddbshim.min.js +3 -3
- package/dist/indexeddbshim.min.js.map +1 -1
- package/dist/nodeSQLiteDatabase.d.ts.map +1 -1
- package/dist/nodeWebSQL.d.ts.map +1 -1
- package/package.json +8 -9
- package/src/CFG.js +2 -0
- package/src/DOMException.js +21 -21
- package/src/IDBFactory.js +88 -39
- package/src/IDBObjectStore.js +1 -1
- package/src/IDBTransaction.js +7 -1
- package/src/Key.js +34 -12
- package/src/Sca.js +53 -3
- package/src/nodeSQLiteDatabase.js +10 -1
- package/src/nodeWebSQL.js +3 -0
- package/src/setGlobalVars.js +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodeSQLiteDatabase.d.ts","sourceRoot":"","sources":["../src/nodeSQLiteDatabase.js"],"names":[],"mappings":";iCAyBa,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI;+BAIvC,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC,GAAC,SAAS;AAkC9C;;;;;;GAMG;AACH;SAHgB,GAAG;gBAAc,MAAM;SAF5B,MAAM,SACN;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,OAAO,CAAC,EAAE,kBAAkB,CAAA;CAAC,GAEjF,IAAI,
|
|
1
|
+
{"version":3,"file":"nodeSQLiteDatabase.d.ts","sourceRoot":"","sources":["../src/nodeSQLiteDatabase.js"],"names":[],"mappings":";iCAyBa,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI;+BAIvC,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC,GAAC,SAAS;AAkC9C;;;;;;GAMG;AACH;SAHgB,GAAG;gBAAc,MAAM;SAF5B,MAAM,SACN;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,OAAO,CAAC,EAAE,kBAAkB,CAAA;CAAC,GAEjF,IAAI,CA4EhB;;IAjFD;;;;;;OAMG;IACH;aAHgB,GAAG;oBAAc,MAAM;aAF5B,MAAM,SACN;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;QAAC,OAAO,CAAC,EAAE,kBAAkB,CAAA;KAAC,EA8E7F;IAzEG,mBAAsB;IAkBtB,SAsDE;IAyBN;;;;;OAKG;IACH,cALW;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,EAAE,CAAA;KAAC,EAAE,YAChC,OAAO,YACP,CAAC,GAAG,EAAE,KAAK,GAAC,IAAI,EAAE,OAAO,CAAC,EAAE,YAAY,EAAE,KAAK,IAAI,GACjD,IAAI,CA2IhB;;AArTD;;GAEG;AACH;IACI;;;;;OAKG;IACH,mBALW,KAAK,GAAC,IAAI,GAAC,SAAS,aACpB,MAAM,GAAC,SAAS,iBAChB,MAAM,SACN,MAAM,EAAE,EAOlB;IAJG,gCAAkB;IAClB,6BAAwB;IACxB,iCAAgC;IAChC,2BAAgB;CAEvB"}
|
package/dist/nodeWebSQL.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodeWebSQL.d.ts","sourceRoot":"","sources":["../src/nodeWebSQL.js"],"names":[],"mappings":";qCAKa;IACR,GAAG,EAAE,GAAG,CAAC;IACT,IAAI,EAAE,CAAA,OAAO,cAAc,EAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAA;CACjD;;;;;;;;;;;wCAYS,KAAK,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,sBAAsB;
|
|
1
|
+
{"version":3,"file":"nodeWebSQL.d.ts","sourceRoot":"","sources":["../src/nodeWebSQL.js"],"names":[],"mappings":";qCAKa;IACR,GAAG,EAAE,GAAG,CAAC;IACT,IAAI,EAAE,CAAA,OAAO,cAAc,EAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAA;CACjD;;;;;;;;;;;wCAYS,KAAK,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,sBAAsB;AAgCrE,qHAAsK;2BAnD3I,yBAAyB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "indexeddbshim",
|
|
3
|
-
"version": "17.
|
|
3
|
+
"version": "17.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "Parashuram <code@nparashuram.com>",
|
|
6
6
|
"contributors": [
|
|
@@ -47,13 +47,13 @@
|
|
|
47
47
|
"clean-mocha": "rimraf D_indexeddbshim_test_database_* D_test.sqlite",
|
|
48
48
|
"clean-fake": "rimraf D_test0.*",
|
|
49
49
|
"clean-mock": "rimraf D_test_database*",
|
|
50
|
-
"clean-w3c": "rimraf D_^D^B2* D_db* D_test* D_about* D_^I^D^B* D_blank* D_database_name* D_idbtransaction* D_x D_x.sqlite D_y D_y.sqlite D_webworker* D_http*",
|
|
50
|
+
"clean-w3c": "rimraf D_opaque* D_inbox* D_output* D_*_bucket_* D_^D^B2* D_db* D_test* D_about* D_^I^D^B* D_blank* D_database_name* D_idbtransaction* D_x D_x.sqlite D_y D_y.sqlite D_webworker* D_http*",
|
|
51
51
|
"clean-w3cOld": "rimraf D_db.sqlite* D_test* D_database_name* D_idbtransaction*",
|
|
52
52
|
"clean-w3c-built": "rimraf test-support/js",
|
|
53
53
|
"copy": "copyup node_modules/source-map-support/browser-source-map-support.js node_modules/mocha/mocha.css node_modules/mocha/mocha.js node_modules/chai/chai.js node_modules/sinon/pkg/sinon-no-sourcemaps.js test-support",
|
|
54
54
|
"fix-permissions": "chmod +x node_modules/npm-run-all/bin/*/index.js",
|
|
55
55
|
"lint": "eslint .",
|
|
56
|
-
"eslint": "npm run lint",
|
|
56
|
+
"eslint": "npm run lint --",
|
|
57
57
|
"sqlite-rebuild": "cd node_modules/sqlite3 && npm i",
|
|
58
58
|
"w3c-build-only": "node test-support/node-buildjs",
|
|
59
59
|
"w3c-build": "run-s clean-w3c clean-w3c-built w3c-build-only",
|
|
@@ -172,7 +172,7 @@
|
|
|
172
172
|
"eventtargeter": "0.12.0",
|
|
173
173
|
"sync-promise-expanded": "^2.0.0",
|
|
174
174
|
"typeson": "10.2.0",
|
|
175
|
-
"typeson-registry": "14.
|
|
175
|
+
"typeson-registry": "14.3.0",
|
|
176
176
|
"websql-configurable": "^3.1.0"
|
|
177
177
|
},
|
|
178
178
|
"devDependencies": {
|
|
@@ -186,9 +186,9 @@
|
|
|
186
186
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
187
187
|
"@rollup/plugin-terser": "^1.0.0",
|
|
188
188
|
"@types/better-sqlite3": "^9.6.0",
|
|
189
|
-
"@types/node": "^26.
|
|
189
|
+
"@types/node": "^26.4.0",
|
|
190
190
|
"@types/websql": "^0.0.30",
|
|
191
|
-
"@unicode/unicode-17.0.0": "^
|
|
191
|
+
"@unicode/unicode-17.0.0": "^2.0.2",
|
|
192
192
|
"babel-plugin-add-module-exports": "1.0.4",
|
|
193
193
|
"bson": "^7.3.2",
|
|
194
194
|
"builtin-modules": "^5.3.0",
|
|
@@ -198,7 +198,6 @@
|
|
|
198
198
|
"colors": "1.4.0",
|
|
199
199
|
"copyfiles": "^2.4.1",
|
|
200
200
|
"coveradge": "^0.8.2",
|
|
201
|
-
"cyclonejs": "1.1.4",
|
|
202
201
|
"delay-cli": "^3.0.0",
|
|
203
202
|
"eslint": "^10.9.1",
|
|
204
203
|
"eslint-config-ash-nazg": "^42.6.0",
|
|
@@ -207,14 +206,14 @@
|
|
|
207
206
|
"isomorphic-fetch": "^3.0.0",
|
|
208
207
|
"jsdom": "^30.0.1",
|
|
209
208
|
"license-badger": "^0.23.0",
|
|
210
|
-
"local-xmlhttprequest": "
|
|
209
|
+
"local-xmlhttprequest": "4.0.0",
|
|
211
210
|
"mocha": "^11.8.0",
|
|
212
211
|
"mocha-badge-generator": "^0.11.0",
|
|
213
212
|
"mocha-multi-reporters": "^1.5.1",
|
|
214
213
|
"npm-run-all": "^4.1.5",
|
|
215
214
|
"open-cli": "^9.0.0",
|
|
216
215
|
"rimraf": "^6.1.3",
|
|
217
|
-
"rollup": "^4.
|
|
216
|
+
"rollup": "^4.63.0",
|
|
218
217
|
"rollup-plugin-filesize": "^10.0.0",
|
|
219
218
|
"rollup-plugin-node-polyfills": "^0.2.1",
|
|
220
219
|
"sinon": "^22.1.0",
|
package/src/CFG.js
CHANGED
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
* sqlBusyTimeout: number,
|
|
44
44
|
* sqlTrace: () => void,
|
|
45
45
|
* sqlProfile: () => void,
|
|
46
|
+
* sqlMemoryQuota: number,
|
|
46
47
|
* escapeNULForSQLiteStatements: boolean,
|
|
47
48
|
* createIndexes: boolean
|
|
48
49
|
* }} ConfigValues
|
|
@@ -220,6 +221,7 @@ const CFG = /** @type {ConfigValues} */ ({});
|
|
|
220
221
|
// Defaults to true except in Node builds where we can preserve literal NUL with better-sqlite3
|
|
221
222
|
'escapeNULForSQLiteStatements',
|
|
222
223
|
|
|
224
|
+
'sqlMemoryQuota',
|
|
223
225
|
'createIndexes'
|
|
224
226
|
]).forEach((prop) => {
|
|
225
227
|
/** @type {(val: any) => void} */
|
package/src/DOMException.js
CHANGED
|
@@ -330,15 +330,14 @@ function findError (args) {
|
|
|
330
330
|
* optional here and, in practice, always `undefined` today (the `case 4`/
|
|
331
331
|
* `case 7` branches below are effectively unreachable pending upstream
|
|
332
332
|
* support for surfacing a real error code).
|
|
333
|
-
* @param {Error & {code?: number}} webSQLErr
|
|
333
|
+
* @param {Error & {code?: number|string}} webSQLErr
|
|
334
334
|
* @returns {(DOMException|Error) & {
|
|
335
|
-
* sqlError: Error & {code?: number}
|
|
335
|
+
* sqlError: Error & {code?: number|string}
|
|
336
336
|
* }|QuotaExceededError}
|
|
337
337
|
*/
|
|
338
338
|
function webSQLErrback (webSQLErr) {
|
|
339
339
|
let name, message, useQuotaExceededError = false;
|
|
340
|
-
|
|
341
|
-
case 4: { // SQLError.QUOTA_ERR
|
|
340
|
+
if (webSQLErr.code === 4 || webSQLErr.code === 'SQLITE_FULL') { // SQLError.QUOTA_ERR or better-sqlite3 SQLITE_FULL
|
|
342
341
|
name = 'QuotaExceededError';
|
|
343
342
|
message = 'The operation failed because there was not enough ' +
|
|
344
343
|
'remaining storage space, or the storage quota was reached ' +
|
|
@@ -346,22 +345,23 @@ function webSQLErrback (webSQLErr) {
|
|
|
346
345
|
if (typeof QuotaExceededError !== 'undefined') {
|
|
347
346
|
useQuotaExceededError = true;
|
|
348
347
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
348
|
+
} else {
|
|
349
|
+
switch (webSQLErr.code) {
|
|
350
|
+
/*
|
|
351
|
+
// Should a WebSQL timeout treat as IndexedDB `TransactionInactiveError` or `UnknownError`?
|
|
352
|
+
case 7: { // SQLError.TIMEOUT_ERR
|
|
353
|
+
// All transaction errors abort later, so no need to mark inactive
|
|
354
|
+
name = 'TransactionInactiveError';
|
|
355
|
+
message = 'A request was placed against a transaction which is currently not active, or which is finished (Internal SQL Timeout).';
|
|
356
|
+
break;
|
|
357
|
+
}
|
|
358
|
+
*/
|
|
359
|
+
default: {
|
|
360
|
+
name = 'UnknownError';
|
|
361
|
+
message = 'The operation failed for reasons unrelated to the database itself and not covered by any other errors.';
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
365
|
}
|
|
366
366
|
message += ' (' + webSQLErr.message + ')--(' + webSQLErr.code + ')';
|
|
367
367
|
|
|
@@ -372,7 +372,7 @@ function webSQLErrback (webSQLErr) {
|
|
|
372
372
|
const err =
|
|
373
373
|
/**
|
|
374
374
|
* @type {(Error | DOMException) & {
|
|
375
|
-
* sqlError: Error & {code?: number}
|
|
375
|
+
* sqlError: Error & {code?: number|string}
|
|
376
376
|
* }}
|
|
377
377
|
*/
|
|
378
378
|
(createDOMException(name, message));
|
package/src/IDBFactory.js
CHANGED
|
@@ -557,6 +557,7 @@ IDBFactory.prototype.open = function (name /* , version */) {
|
|
|
557
557
|
|
|
558
558
|
const req = IDBOpenDBRequest.__createInstance();
|
|
559
559
|
let calledDbCreateError = false;
|
|
560
|
+
let isRevertingSysdb = false;
|
|
560
561
|
|
|
561
562
|
if (CFG.autoName && name === '') {
|
|
562
563
|
// eslint-disable-next-line unicorn/no-top-level-assignment-in-function -- Necessary?
|
|
@@ -585,7 +586,7 @@ IDBFactory.prototype.open = function (name /* , version */) {
|
|
|
585
586
|
* @returns {boolean}
|
|
586
587
|
*/
|
|
587
588
|
function dbCreateError (tx, err) {
|
|
588
|
-
if (calledDbCreateError) {
|
|
589
|
+
if (calledDbCreateError || isRevertingSysdb) {
|
|
589
590
|
return false;
|
|
590
591
|
}
|
|
591
592
|
// Defensive cleanup: `pendingVersionChanges.set(name, ...)` (see
|
|
@@ -647,46 +648,63 @@ IDBFactory.prototype.open = function (name /* , version */) {
|
|
|
647
648
|
*/
|
|
648
649
|
let sysdbFinishedCb = function (systx, err, cb) {
|
|
649
650
|
if (err) {
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
651
|
+
/**
|
|
652
|
+
* @param {any} [errorToShow]
|
|
653
|
+
* @returns {void}
|
|
654
|
+
*/
|
|
655
|
+
const manualRevert = function (errorToShow) {
|
|
656
|
+
/**
|
|
657
|
+
* @param {string} [msg]
|
|
658
|
+
* @throws {Error}
|
|
659
|
+
* @returns {never}
|
|
660
|
+
*/
|
|
661
|
+
function reportError (msg) {
|
|
662
|
+
throw new Error('Unable to roll back upgrade transaction!' + (msg || ''));
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
sysdb.transaction(
|
|
666
|
+
function (systx) {
|
|
667
|
+
// Attempt to revert
|
|
668
|
+
if (oldVersion === 0) {
|
|
669
|
+
systx.executeSql(
|
|
670
|
+
'DELETE FROM dbVersions WHERE "name" = ?',
|
|
671
|
+
[sqlSafeName]
|
|
672
|
+
);
|
|
673
|
+
} else {
|
|
674
|
+
systx.executeSql(
|
|
675
|
+
'UPDATE dbVersions SET "version" = ? WHERE "name" = ?',
|
|
676
|
+
[oldVersion, sqlSafeName]
|
|
677
|
+
);
|
|
678
|
+
}
|
|
679
|
+
},
|
|
680
|
+
function (sqlErr) {
|
|
681
|
+
isRevertingSysdb = false;
|
|
682
|
+
cb(sqlErr); // eslint-disable-line promise/no-callback-in-promise -- Convenient
|
|
683
|
+
},
|
|
684
|
+
function () {
|
|
685
|
+
isRevertingSysdb = false;
|
|
686
|
+
cb(errorToShow || reportError); // eslint-disable-line promise/no-callback-in-promise -- Convenient
|
|
664
687
|
}
|
|
688
|
+
);
|
|
689
|
+
};
|
|
665
690
|
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
);
|
|
678
|
-
} else {
|
|
679
|
-
systx.executeSql(
|
|
680
|
-
'UPDATE dbVersions SET "version" = ? WHERE "name" = ?',
|
|
681
|
-
[
|
|
682
|
-
oldVersion, sqlSafeName
|
|
683
|
-
],
|
|
684
|
-
cb,
|
|
685
|
-
// @ts-expect-error Force to work
|
|
686
|
-
reportError
|
|
687
|
-
);
|
|
691
|
+
try {
|
|
692
|
+
systx.executeSql(
|
|
693
|
+
'ROLLBACK',
|
|
694
|
+
[],
|
|
695
|
+
function () {
|
|
696
|
+
cb(); // eslint-disable-line promise/no-callback-in-promise -- Convenient
|
|
697
|
+
},
|
|
698
|
+
function (tx, sqlErr) {
|
|
699
|
+
// Browser/Node may fail with expired transaction, so manually revert
|
|
700
|
+
manualRevert(sqlErr);
|
|
701
|
+
return false;
|
|
688
702
|
}
|
|
689
|
-
|
|
703
|
+
);
|
|
704
|
+
} catch (e) {
|
|
705
|
+
// Browser may fail with expired transaction above so
|
|
706
|
+
// no choice but to manually revert
|
|
707
|
+
manualRevert(e);
|
|
690
708
|
}
|
|
691
709
|
return;
|
|
692
710
|
}
|
|
@@ -790,6 +808,7 @@ IDBFactory.prototype.open = function (name /* , version */) {
|
|
|
790
808
|
|
|
791
809
|
// eslint-disable-next-line camelcase -- Clear API
|
|
792
810
|
req.transaction.on__preabort = function () {
|
|
811
|
+
isRevertingSysdb = true;
|
|
793
812
|
pendingVersionChanges.delete(name);
|
|
794
813
|
connection.__upgradeTransaction = null;
|
|
795
814
|
// We ensure any cache is deleted before any request error events fire and try to reopen
|
|
@@ -808,6 +827,7 @@ IDBFactory.prototype.open = function (name /* , version */) {
|
|
|
808
827
|
req.__done = false;
|
|
809
828
|
|
|
810
829
|
connection.close();
|
|
830
|
+
isRevertingSysdb = true;
|
|
811
831
|
setTimeout(() => {
|
|
812
832
|
const err = createDOMException('AbortError', 'The upgrade transaction was aborted.');
|
|
813
833
|
sysdbFinishedCb(systx, err, function (reportError) {
|
|
@@ -876,7 +896,36 @@ IDBFactory.prototype.open = function (name /* , version */) {
|
|
|
876
896
|
}
|
|
877
897
|
sysdbFinishedCb = function (systx, err, cb) {
|
|
878
898
|
if (err) {
|
|
879
|
-
rollback(err,
|
|
899
|
+
rollback(err,
|
|
900
|
+
/**
|
|
901
|
+
* @param {Error} [reportError]
|
|
902
|
+
* @returns {void}
|
|
903
|
+
*/
|
|
904
|
+
function (reportError) {
|
|
905
|
+
sysdb.transaction(
|
|
906
|
+
function (systx) {
|
|
907
|
+
if (oldVersion === 0) {
|
|
908
|
+
systx.executeSql(
|
|
909
|
+
'DELETE FROM dbVersions WHERE "name" = ?',
|
|
910
|
+
[sqlSafeName]
|
|
911
|
+
);
|
|
912
|
+
} else {
|
|
913
|
+
systx.executeSql(
|
|
914
|
+
'UPDATE dbVersions SET "version" = ? WHERE "name" = ?',
|
|
915
|
+
[oldVersion, sqlSafeName]
|
|
916
|
+
);
|
|
917
|
+
}
|
|
918
|
+
},
|
|
919
|
+
function (sqlErr) {
|
|
920
|
+
isRevertingSysdb = false;
|
|
921
|
+
cb(sqlErr); // eslint-disable-line promise/no-callback-in-promise -- Convenient
|
|
922
|
+
},
|
|
923
|
+
function () {
|
|
924
|
+
isRevertingSysdb = false;
|
|
925
|
+
cb(reportError); // eslint-disable-line promise/no-callback-in-promise -- Convenient
|
|
926
|
+
}
|
|
927
|
+
);
|
|
928
|
+
});
|
|
880
929
|
} else {
|
|
881
930
|
commit(cb);
|
|
882
931
|
}
|
package/src/IDBObjectStore.js
CHANGED
|
@@ -322,7 +322,7 @@ IDBObjectStore.__createObjectStore = function (db, store) {
|
|
|
322
322
|
encodedKeyPath,
|
|
323
323
|
// For why converting here, see comment and following
|
|
324
324
|
// discussion at:
|
|
325
|
-
// https://github.com/
|
|
325
|
+
// https://github.com/indexeddbshim/IndexedDBShim/issues/313#issuecomment-590086778
|
|
326
326
|
Number(store.autoIncrement),
|
|
327
327
|
'{}',
|
|
328
328
|
1
|
package/src/IDBTransaction.js
CHANGED
|
@@ -8,6 +8,7 @@ import IDBObjectStore from './IDBObjectStore.js';
|
|
|
8
8
|
import CFG from './CFG.js';
|
|
9
9
|
|
|
10
10
|
let uniqueID = 0;
|
|
11
|
+
const activeTransactions = new Set();
|
|
11
12
|
const listeners = ['onabort', 'oncomplete', 'onerror'];
|
|
12
13
|
const readonlyProperties = ['objectStoreNames', 'mode', 'durability', 'db', 'error'];
|
|
13
14
|
|
|
@@ -137,6 +138,7 @@ IDBTransaction.__createInstance = function (db, storeNames, mode, durability = '
|
|
|
137
138
|
me.__mode = mode;
|
|
138
139
|
me.__durability = durability;
|
|
139
140
|
me.__db = db;
|
|
141
|
+
activeTransactions.add(me);
|
|
140
142
|
me.__error = null;
|
|
141
143
|
// @ts-expect-error Part of `ShimEventTarget`
|
|
142
144
|
me.__setOptions({
|
|
@@ -641,6 +643,7 @@ IDBTransaction.prototype.__executeRequests = function () {
|
|
|
641
643
|
me.__errored = true;
|
|
642
644
|
throw e;
|
|
643
645
|
} finally {
|
|
646
|
+
activeTransactions.delete(me);
|
|
644
647
|
me.__storeHandles = {};
|
|
645
648
|
}
|
|
646
649
|
}
|
|
@@ -855,6 +858,7 @@ IDBTransaction.prototype.__abortTransaction = function (err) {
|
|
|
855
858
|
});
|
|
856
859
|
}
|
|
857
860
|
me.__active = false; // Setting here and in requestsFinished for https://github.com/w3c/IndexedDB/issues/87
|
|
861
|
+
activeTransactions.delete(me);
|
|
858
862
|
|
|
859
863
|
if (err !== null) {
|
|
860
864
|
me.__error = err;
|
|
@@ -1064,7 +1068,7 @@ IDBTransaction.__assertNotFinishedObjectStoreMethod = function (tx) {
|
|
|
1064
1068
|
* @returns {void}
|
|
1065
1069
|
*/
|
|
1066
1070
|
IDBTransaction.__assertActive = function (tx) {
|
|
1067
|
-
if (!tx || !tx.__active || tx.__committed) {
|
|
1071
|
+
if (!tx || !tx.__active || !tx.__handlerActive || tx.__committed) {
|
|
1068
1072
|
throw createDOMException('TransactionInactiveError', 'A request was placed against a transaction which is currently not active, or which is finished');
|
|
1069
1073
|
}
|
|
1070
1074
|
};
|
|
@@ -1095,4 +1099,6 @@ Object.defineProperty(IDBTransaction, 'prototype', {
|
|
|
1095
1099
|
});
|
|
1096
1100
|
/* eslint-enable unicorn/no-top-level-side-effects -- Would be good */
|
|
1097
1101
|
|
|
1102
|
+
IDBTransaction.activeTransactions = activeTransactions;
|
|
1103
|
+
|
|
1098
1104
|
export default IDBTransaction;
|
package/src/Key.js
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {unknown[]} arr
|
|
3
|
+
* @param {number} index
|
|
4
|
+
* @param {unknown} val
|
|
5
|
+
* @returns {void}
|
|
6
|
+
*/
|
|
7
|
+
const setArrayValue = (arr, index, val) => {
|
|
8
|
+
if (Reflect.has(Array.prototype, index)) {
|
|
9
|
+
Object.defineProperty(arr, index, {value: val, enumerable: true, writable: true, configurable: true});
|
|
10
|
+
} else {
|
|
11
|
+
arr[index] = val;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* @param {unknown[]} arr
|
|
16
|
+
* @param {unknown} val
|
|
17
|
+
* @returns {void}
|
|
18
|
+
*/
|
|
19
|
+
const safePush = (arr, val) => setArrayValue(arr, arr.length, val);
|
|
1
20
|
import {createDOMException} from './DOMException.js';
|
|
2
21
|
import * as util from './util.js';
|
|
3
22
|
import cmp from './cmp.js';
|
|
@@ -281,12 +300,13 @@ const types = {
|
|
|
281
300
|
* @returns {string}
|
|
282
301
|
*/
|
|
283
302
|
encode (key) {
|
|
303
|
+
/** @type {(string|null)[]} */
|
|
284
304
|
const encoded = [];
|
|
285
305
|
for (const [i, item] of key.entries()) {
|
|
286
306
|
const encodedItem = encode(item, true); // encode the array item
|
|
287
|
-
encoded
|
|
307
|
+
setArrayValue(encoded, i, encodedItem);
|
|
288
308
|
}
|
|
289
|
-
encoded
|
|
309
|
+
safePush(encoded, keyTypeToEncodedChar.invalid + '-'); // append an extra item, so empty arrays sort correctly
|
|
290
310
|
let encodedKey = JSON.stringify(encoded);
|
|
291
311
|
if (CFG.escapeNULForSQLiteStatements === false) {
|
|
292
312
|
encodedKey = encodedKey.replaceAll(String.raw`\u0000`, '\0');
|
|
@@ -307,7 +327,7 @@ const types = {
|
|
|
307
327
|
for (let i = 0; i < decoded.length; i++) {
|
|
308
328
|
const item = decoded[i];
|
|
309
329
|
const decodedItem = decode(item, true); // decode the item
|
|
310
|
-
decoded
|
|
330
|
+
setArrayValue(decoded, i, decodedItem);
|
|
311
331
|
}
|
|
312
332
|
return decoded;
|
|
313
333
|
}
|
|
@@ -577,7 +597,7 @@ function convertValueToKeyValueDecoded (input, seen, multiEntry, fullKeys) {
|
|
|
577
597
|
} case 'array': { // May throw (from binary)
|
|
578
598
|
const arr = /** @type {Array<any>} */ (input);
|
|
579
599
|
const len = arr.length;
|
|
580
|
-
seen
|
|
600
|
+
safePush(seen, input);
|
|
581
601
|
|
|
582
602
|
/** @type {(KeyValueObject|Value)[]} */
|
|
583
603
|
const keys = [];
|
|
@@ -598,7 +618,7 @@ function convertValueToKeyValueDecoded (input, seen, multiEntry, fullKeys) {
|
|
|
598
618
|
(!fullKeys && keys.every((k) => cmp(k, key.value) !== 0)) ||
|
|
599
619
|
(fullKeys && keys.every((k) => cmp(k, key) !== 0))
|
|
600
620
|
) {
|
|
601
|
-
keys
|
|
621
|
+
safePush(keys, fullKeys ? key : key.value);
|
|
602
622
|
}
|
|
603
623
|
} catch (err) {
|
|
604
624
|
if (!multiEntry) {
|
|
@@ -732,7 +752,7 @@ function evaluateKeyPathOnValueToDecodedValue (value, keyPath, multiEntry, fullK
|
|
|
732
752
|
if (key.failure) {
|
|
733
753
|
return true;
|
|
734
754
|
}
|
|
735
|
-
result
|
|
755
|
+
safePush(result, key.value);
|
|
736
756
|
return false;
|
|
737
757
|
})
|
|
738
758
|
? {failure: true}
|
|
@@ -793,11 +813,11 @@ function injectKeyIntoValueUsingKeyPath (value, key, keyPath) {
|
|
|
793
813
|
identifiers.forEach((identifier) => {
|
|
794
814
|
const hop = Object.hasOwn(value, identifier);
|
|
795
815
|
if (!hop) {
|
|
796
|
-
value
|
|
816
|
+
Object.defineProperty(value, identifier, {value: {}, enumerable: true, writable: true, configurable: true});
|
|
797
817
|
}
|
|
798
818
|
value = value[identifier];
|
|
799
819
|
});
|
|
800
|
-
value
|
|
820
|
+
Object.defineProperty(value, /** @type {string} */ (last), {value: key, enumerable: true, writable: true, configurable: true}); // key is already a `keyValue` in our processing so no need to convert
|
|
801
821
|
}
|
|
802
822
|
|
|
803
823
|
/**
|
|
@@ -883,6 +903,7 @@ function isMultiEntryMatch (encodedEntry, encodedKey) {
|
|
|
883
903
|
* @returns {Key[]}
|
|
884
904
|
*/
|
|
885
905
|
function findMultiEntryMatches (keyEntry, range) {
|
|
906
|
+
/** @type {unknown[]} */
|
|
886
907
|
const matches = [];
|
|
887
908
|
|
|
888
909
|
if (Array.isArray(keyEntry)) {
|
|
@@ -896,18 +917,18 @@ function findMultiEntryMatches (keyEntry, range) {
|
|
|
896
917
|
} else {
|
|
897
918
|
const nested = findMultiEntryMatches(key, range);
|
|
898
919
|
if (nested.length > 0) {
|
|
899
|
-
matches
|
|
920
|
+
safePush(matches, key);
|
|
900
921
|
}
|
|
901
922
|
continue;
|
|
902
923
|
}
|
|
903
924
|
}
|
|
904
925
|
|
|
905
926
|
if (util.isNullish(range) || isKeyInRange(key, range, true)) {
|
|
906
|
-
matches
|
|
927
|
+
safePush(matches, key);
|
|
907
928
|
}
|
|
908
929
|
}
|
|
909
930
|
} else if (util.isNullish(range) || isKeyInRange(keyEntry, range, true)) {
|
|
910
|
-
matches
|
|
931
|
+
safePush(matches, keyEntry);
|
|
911
932
|
}
|
|
912
933
|
return matches;
|
|
913
934
|
}
|
|
@@ -924,12 +945,13 @@ function convertKeyToValue (key) {
|
|
|
924
945
|
case 'number': case 'string': {
|
|
925
946
|
return value;
|
|
926
947
|
} case 'array': {
|
|
948
|
+
/** @type {ValueType[]} */
|
|
927
949
|
const array = [];
|
|
928
950
|
const len = value.length;
|
|
929
951
|
let index = 0;
|
|
930
952
|
while (index < len) {
|
|
931
953
|
const entry = convertKeyToValue(value[index]);
|
|
932
|
-
array
|
|
954
|
+
setArrayValue(array, index, entry);
|
|
933
955
|
index++;
|
|
934
956
|
}
|
|
935
957
|
return array;
|
package/src/Sca.js
CHANGED
|
@@ -1,12 +1,62 @@
|
|
|
1
1
|
import {
|
|
2
|
-
Typeson, hasConstructorOf,
|
|
2
|
+
Typeson, hasConstructorOf, structuredCloningForStorage
|
|
3
3
|
} from 'typeson-registry';
|
|
4
4
|
|
|
5
5
|
import {createDOMException, ShimDOMException} from './DOMException.js';
|
|
6
6
|
|
|
7
7
|
// See: https://stackoverflow.com/questions/42170826/categories-for-rejection-by-the-structured-cloning-algorithm
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
// Although typeson-registry already has a FileList type in its structured cloning presets,
|
|
10
|
+
// we need to override it so it works with our tests
|
|
11
|
+
|
|
12
|
+
const specSet = structuredCloningForStorage
|
|
13
|
+
.flatMap((preset) => (Array.isArray(preset) ? preset : [preset]))
|
|
14
|
+
.find((preset) => preset && !Array.isArray(preset) && 'filelist' in preset);
|
|
15
|
+
|
|
16
|
+
const origFileList = specSet && !Array.isArray(specSet) && 'filelist' in specSet
|
|
17
|
+
? specSet.filelist
|
|
18
|
+
: undefined;
|
|
19
|
+
|
|
20
|
+
const origTest = origFileList && typeof origFileList === 'object' && 'test' in origFileList && typeof origFileList.test === 'function'
|
|
21
|
+
? origFileList.test
|
|
22
|
+
: undefined;
|
|
23
|
+
|
|
24
|
+
const origRevive = origFileList && typeof origFileList === 'object' && 'revive' in origFileList && typeof origFileList.revive === 'function'
|
|
25
|
+
? origFileList.revive
|
|
26
|
+
: undefined;
|
|
27
|
+
|
|
28
|
+
const customFileList = origFileList
|
|
29
|
+
? {
|
|
30
|
+
...origFileList,
|
|
31
|
+
/**
|
|
32
|
+
* @param {unknown} x
|
|
33
|
+
* @param {import('typeson').StateObject} state
|
|
34
|
+
* @returns {boolean}
|
|
35
|
+
*/
|
|
36
|
+
test (x, state) {
|
|
37
|
+
if (typeof FileList !== 'undefined') {
|
|
38
|
+
return x instanceof FileList;
|
|
39
|
+
}
|
|
40
|
+
return typeof origTest === 'function' ? origTest(x, state) : false;
|
|
41
|
+
},
|
|
42
|
+
/**
|
|
43
|
+
* @param {unknown} x
|
|
44
|
+
* @param {import('typeson').StateObject} state
|
|
45
|
+
* @returns {unknown}
|
|
46
|
+
*/
|
|
47
|
+
revive (x, state) {
|
|
48
|
+
if (typeof FileList !== 'undefined') {
|
|
49
|
+
return Reflect.construct(FileList, [x]);
|
|
50
|
+
}
|
|
51
|
+
return typeof origRevive === 'function' ? origRevive(x, state) : undefined;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
: undefined;
|
|
55
|
+
|
|
56
|
+
let typeson = new Typeson().register([
|
|
57
|
+
structuredCloningForStorage,
|
|
58
|
+
customFileList ? {filelist: customFileList} : {}
|
|
59
|
+
]);
|
|
10
60
|
|
|
11
61
|
/**
|
|
12
62
|
* @param {(preset: import('typeson-registry').Preset) =>
|
|
@@ -15,7 +65,7 @@ let typeson = new Typeson().register(structuredCloningThrowing);
|
|
|
15
65
|
*/
|
|
16
66
|
function register (func) {
|
|
17
67
|
// eslint-disable-next-line unicorn/no-top-level-assignment-in-function -- Should be one-time cache
|
|
18
|
-
typeson = new Typeson().register(func(
|
|
68
|
+
typeson = new Typeson().register(func(structuredCloningForStorage));
|
|
19
69
|
}
|
|
20
70
|
|
|
21
71
|
/**
|
|
@@ -91,7 +91,7 @@ function SQLiteDatabase (name, opts = {}) {
|
|
|
91
91
|
_db: db,
|
|
92
92
|
/**
|
|
93
93
|
* Compatibility with node-sqlite3's configure API.
|
|
94
|
-
* @param {'busyTimeout'|'trace'|'profile'} option
|
|
94
|
+
* @param {'busyTimeout'|'trace'|'profile'|'memoryQuota'} option
|
|
95
95
|
* @param {number|((sql: string, duration?: number) => void)} value
|
|
96
96
|
* @returns {void}
|
|
97
97
|
*/
|
|
@@ -106,6 +106,15 @@ function SQLiteDatabase (name, opts = {}) {
|
|
|
106
106
|
}
|
|
107
107
|
if (option === 'profile') {
|
|
108
108
|
profile = /** @type {SQLProfileCallback} */ (value);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (option === 'memoryQuota') {
|
|
112
|
+
const bytes = Number(value);
|
|
113
|
+
// `better-sqlite3` doesn't have a direct `sqlite3_quota_set` binding,
|
|
114
|
+
// but we can limit the max pages:
|
|
115
|
+
const pageSizeObj = db.pragma('page_size', {simple: true});
|
|
116
|
+
const pageSize = Number(pageSizeObj);
|
|
117
|
+
db.pragma('max_page_count = ' + Math.ceil(bytes / pageSize));
|
|
109
118
|
}
|
|
110
119
|
},
|
|
111
120
|
/**
|
package/src/nodeWebSQL.js
CHANGED