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.
Files changed (43) hide show
  1. package/README.md +3 -146
  2. package/dist/CFG.d.ts +1 -0
  3. package/dist/CFG.d.ts.map +1 -1
  4. package/dist/DOMException.d.ts +4 -4
  5. package/dist/DOMException.d.ts.map +1 -1
  6. package/dist/IDBFactory.d.ts.map +1 -1
  7. package/dist/IDBTransaction.d.ts +8 -6
  8. package/dist/IDBTransaction.d.ts.map +1 -1
  9. package/dist/Key.d.ts.map +1 -1
  10. package/dist/Sca.d.ts.map +1 -1
  11. package/dist/indexeddbshim-Key.js +54 -14
  12. package/dist/indexeddbshim-Key.js.map +1 -1
  13. package/dist/indexeddbshim-Key.min.js +2 -2
  14. package/dist/indexeddbshim-Key.min.js.map +1 -1
  15. package/dist/indexeddbshim-UnicodeIdentifiers-node.cjs +212 -80
  16. package/dist/indexeddbshim-UnicodeIdentifiers-node.cjs.map +1 -1
  17. package/dist/indexeddbshim-UnicodeIdentifiers.js +201 -79
  18. package/dist/indexeddbshim-UnicodeIdentifiers.js.map +1 -1
  19. package/dist/indexeddbshim-UnicodeIdentifiers.min.js +3 -3
  20. package/dist/indexeddbshim-UnicodeIdentifiers.min.js.map +1 -1
  21. package/dist/indexeddbshim-node.cjs +212 -80
  22. package/dist/indexeddbshim-node.cjs.map +1 -1
  23. package/dist/indexeddbshim-noninvasive.js +201 -79
  24. package/dist/indexeddbshim-noninvasive.js.map +1 -1
  25. package/dist/indexeddbshim-noninvasive.min.js +3 -3
  26. package/dist/indexeddbshim-noninvasive.min.js.map +1 -1
  27. package/dist/indexeddbshim.js +201 -79
  28. package/dist/indexeddbshim.js.map +1 -1
  29. package/dist/indexeddbshim.min.js +3 -3
  30. package/dist/indexeddbshim.min.js.map +1 -1
  31. package/dist/nodeSQLiteDatabase.d.ts.map +1 -1
  32. package/dist/nodeWebSQL.d.ts.map +1 -1
  33. package/package.json +8 -9
  34. package/src/CFG.js +2 -0
  35. package/src/DOMException.js +21 -21
  36. package/src/IDBFactory.js +88 -39
  37. package/src/IDBObjectStore.js +1 -1
  38. package/src/IDBTransaction.js +7 -1
  39. package/src/Key.js +34 -12
  40. package/src/Sca.js +53 -3
  41. package/src/nodeSQLiteDatabase.js +10 -1
  42. package/src/nodeWebSQL.js +3 -0
  43. package/src/setGlobalVars.js +3 -3
@@ -1,4 +1,4 @@
1
- /*! indexeddbshim - v17.3.3 - 8/25/2026 */
1
+ /*! indexeddbshim - v17.4.0 - 8/27/2026 */
2
2
 
3
3
  (function (factory) {
4
4
  typeof define === 'function' && define.amd ? define(factory) :
@@ -1754,6 +1754,7 @@
1754
1754
  * sqlBusyTimeout: number,
1755
1755
  * sqlTrace: () => void,
1756
1756
  * sqlProfile: () => void,
1757
+ * sqlMemoryQuota: number,
1757
1758
  * escapeNULForSQLiteStatements: boolean,
1758
1759
  * createIndexes: boolean
1759
1760
  * }} ConfigValues
@@ -1910,7 +1911,7 @@
1910
1911
  'sqlProfile',
1911
1912
  // Callback not used by default
1912
1913
  // Defaults to true except in Node builds where we can preserve literal NUL with better-sqlite3
1913
- 'escapeNULForSQLiteStatements', 'createIndexes'].forEach(function (prop) {
1914
+ 'escapeNULForSQLiteStatements', 'sqlMemoryQuota', 'createIndexes'].forEach(function (prop) {
1914
1915
  /** @type {(val: any) => void} */
1915
1916
  var validator;
1916
1917
  if (Array.isArray(prop)) {
@@ -2931,41 +2932,40 @@
2931
2932
  * optional here and, in practice, always `undefined` today (the `case 4`/
2932
2933
  * `case 7` branches below are effectively unreachable pending upstream
2933
2934
  * support for surfacing a real error code).
2934
- * @param {Error & {code?: number}} webSQLErr
2935
+ * @param {Error & {code?: number|string}} webSQLErr
2935
2936
  * @returns {(DOMException|Error) & {
2936
- * sqlError: Error & {code?: number}
2937
+ * sqlError: Error & {code?: number|string}
2937
2938
  * }|QuotaExceededError}
2938
2939
  */
2939
2940
  function webSQLErrback(webSQLErr) {
2940
2941
  var name,
2941
2942
  message,
2942
2943
  useQuotaExceededError = false;
2943
- switch (webSQLErr.code) {
2944
- case 4:
2945
- {
2946
- // SQLError.QUOTA_ERR
2947
- name = 'QuotaExceededError';
2948
- message = 'The operation failed because there was not enough ' + 'remaining storage space, or the storage quota was reached ' + 'and the user declined to give more space to the database.';
2949
- if (typeof QuotaExceededError !== 'undefined') {
2950
- useQuotaExceededError = true;
2951
- }
2952
- break;
2953
- }
2954
- /*
2955
- // Should a WebSQL timeout treat as IndexedDB `TransactionInactiveError` or `UnknownError`?
2956
- case 7: { // SQLError.TIMEOUT_ERR
2957
- // All transaction errors abort later, so no need to mark inactive
2958
- name = 'TransactionInactiveError';
2959
- message = 'A request was placed against a transaction which is currently not active, or which is finished (Internal SQL Timeout).';
2960
- break;
2944
+ if (webSQLErr.code === 4 || webSQLErr.code === 'SQLITE_FULL') {
2945
+ // SQLError.QUOTA_ERR or better-sqlite3 SQLITE_FULL
2946
+ name = 'QuotaExceededError';
2947
+ message = 'The operation failed because there was not enough ' + 'remaining storage space, or the storage quota was reached ' + 'and the user declined to give more space to the database.';
2948
+ if (typeof QuotaExceededError !== 'undefined') {
2949
+ useQuotaExceededError = true;
2961
2950
  }
2962
- */
2963
- default:
2964
- {
2965
- name = 'UnknownError';
2966
- message = 'The operation failed for reasons unrelated to the database itself and not covered by any other errors.';
2967
- break;
2951
+ } else {
2952
+ switch (webSQLErr.code) {
2953
+ /*
2954
+ // Should a WebSQL timeout treat as IndexedDB `TransactionInactiveError` or `UnknownError`?
2955
+ case 7: { // SQLError.TIMEOUT_ERR
2956
+ // All transaction errors abort later, so no need to mark inactive
2957
+ name = 'TransactionInactiveError';
2958
+ message = 'A request was placed against a transaction which is currently not active, or which is finished (Internal SQL Timeout).';
2959
+ break;
2968
2960
  }
2961
+ */
2962
+ default:
2963
+ {
2964
+ name = 'UnknownError';
2965
+ message = 'The operation failed for reasons unrelated to the database itself and not covered by any other errors.';
2966
+ break;
2967
+ }
2968
+ }
2969
2969
  }
2970
2970
  message += ' (' + webSQLErr.message + ')--(' + webSQLErr.code + ')';
2971
2971
  if (useQuotaExceededError) {
@@ -2974,7 +2974,7 @@
2974
2974
  var err =
2975
2975
  /**
2976
2976
  * @type {(Error | DOMException) & {
2977
- * sqlError: Error & {code?: number}
2977
+ * sqlError: Error & {code?: number|string}
2978
2978
  * }}
2979
2979
  */
2980
2980
  createDOMException(name, message);
@@ -3541,6 +3541,32 @@
3541
3541
  }
3542
3542
 
3543
3543
  var _templateObject, _templateObject2;
3544
+ /**
3545
+ * @param {unknown[]} arr
3546
+ * @param {number} index
3547
+ * @param {unknown} val
3548
+ * @returns {void}
3549
+ */
3550
+ var setArrayValue = function setArrayValue(arr, index, val) {
3551
+ if (Reflect.has(Array.prototype, index)) {
3552
+ Object.defineProperty(arr, index, {
3553
+ value: val,
3554
+ enumerable: true,
3555
+ writable: true,
3556
+ configurable: true
3557
+ });
3558
+ } else {
3559
+ arr[index] = val;
3560
+ }
3561
+ };
3562
+ /**
3563
+ * @param {unknown[]} arr
3564
+ * @param {unknown} val
3565
+ * @returns {void}
3566
+ */
3567
+ var safePush = function safePush(arr, val) {
3568
+ return setArrayValue(arr, arr.length, val);
3569
+ };
3544
3570
 
3545
3571
  /**
3546
3572
  * @typedef {NodeJS.TypedArray|DataView} ArrayBufferView
@@ -3804,6 +3830,7 @@
3804
3830
  * @returns {string}
3805
3831
  */
3806
3832
  encode: function encode(key) {
3833
+ /** @type {(string|null)[]} */
3807
3834
  var encoded = [];
3808
3835
  var _iterator = _createForOfIteratorHelper(key.entries()),
3809
3836
  _step;
@@ -3813,14 +3840,14 @@
3813
3840
  i = _step$value[0],
3814
3841
  item = _step$value[1];
3815
3842
  var encodedItem = _encode(item, true); // encode the array item
3816
- encoded[i] = encodedItem;
3843
+ setArrayValue(encoded, i, encodedItem);
3817
3844
  }
3818
3845
  } catch (err) {
3819
3846
  _iterator.e(err);
3820
3847
  } finally {
3821
3848
  _iterator.f();
3822
3849
  }
3823
- encoded.push(keyTypeToEncodedChar.invalid + '-'); // append an extra item, so empty arrays sort correctly
3850
+ safePush(encoded, keyTypeToEncodedChar.invalid + '-'); // append an extra item, so empty arrays sort correctly
3824
3851
  var encodedKey = JSON.stringify(encoded);
3825
3852
  if (CFG.escapeNULForSQLiteStatements === false) {
3826
3853
  encodedKey = encodedKey.replaceAll(String.raw(_templateObject || (_templateObject = _taggedTemplateLiteral(["\0"], ["\\u0000"]))), '\0');
@@ -3841,7 +3868,7 @@
3841
3868
  for (var i = 0; i < decoded.length; i++) {
3842
3869
  var item = decoded[i];
3843
3870
  var decodedItem = _decode(item, true); // decode the item
3844
- decoded[i] = decodedItem;
3871
+ setArrayValue(decoded, i, decodedItem);
3845
3872
  }
3846
3873
  return decoded;
3847
3874
  }
@@ -4139,7 +4166,7 @@
4139
4166
  // May throw (from binary)
4140
4167
  var arr = /** @type {Array<any>} */input;
4141
4168
  var len = arr.length;
4142
- seen.push(input);
4169
+ safePush(seen, input);
4143
4170
 
4144
4171
  /** @type {(KeyValueObject|Value)[]} */
4145
4172
  var keys = [];
@@ -4174,7 +4201,7 @@
4174
4201
  }) || fullKeys && keys.every(function (k) {
4175
4202
  return cmp(k, key) !== 0;
4176
4203
  })) {
4177
- keys.push(fullKeys ? key : key.value);
4204
+ safePush(keys, fullKeys ? key : key.value);
4178
4205
  }
4179
4206
  } catch (err) {
4180
4207
  if (!multiEntry) {
@@ -4334,7 +4361,7 @@
4334
4361
  if (key.failure) {
4335
4362
  return true;
4336
4363
  }
4337
- result.push(key.value);
4364
+ safePush(result, key.value);
4338
4365
  return false;
4339
4366
  }) ? {
4340
4367
  failure: true
@@ -4395,11 +4422,21 @@
4395
4422
  identifiers.forEach(function (identifier) {
4396
4423
  var hop = Object.hasOwn(value, identifier);
4397
4424
  if (!hop) {
4398
- value[identifier] = {};
4425
+ Object.defineProperty(value, identifier, {
4426
+ value: {},
4427
+ enumerable: true,
4428
+ writable: true,
4429
+ configurable: true
4430
+ });
4399
4431
  }
4400
4432
  value = value[identifier];
4401
4433
  });
4402
- value[(/** @type {string} */last)] = key; // key is already a `keyValue` in our processing so no need to convert
4434
+ Object.defineProperty(value, /** @type {string} */last, {
4435
+ value: key,
4436
+ enumerable: true,
4437
+ writable: true,
4438
+ configurable: true
4439
+ }); // key is already a `keyValue` in our processing so no need to convert
4403
4440
  }
4404
4441
 
4405
4442
  /**
@@ -4477,6 +4514,7 @@
4477
4514
  * @returns {Key[]}
4478
4515
  */
4479
4516
  function findMultiEntryMatches(keyEntry, range) {
4517
+ /** @type {unknown[]} */
4480
4518
  var matches = [];
4481
4519
  if (Array.isArray(keyEntry)) {
4482
4520
  var _iterator4 = _createForOfIteratorHelper(keyEntry),
@@ -4493,13 +4531,13 @@
4493
4531
  } else {
4494
4532
  var nested = findMultiEntryMatches(key, range);
4495
4533
  if (nested.length > 0) {
4496
- matches.push(key);
4534
+ safePush(matches, key);
4497
4535
  }
4498
4536
  continue;
4499
4537
  }
4500
4538
  }
4501
4539
  if (isNullish(range) || isKeyInRange(key, range, true)) {
4502
- matches.push(key);
4540
+ safePush(matches, key);
4503
4541
  }
4504
4542
  }
4505
4543
  } catch (err) {
@@ -4508,7 +4546,7 @@
4508
4546
  _iterator4.f();
4509
4547
  }
4510
4548
  } else if (isNullish(range) || isKeyInRange(keyEntry, range, true)) {
4511
- matches.push(keyEntry);
4549
+ safePush(matches, keyEntry);
4512
4550
  }
4513
4551
  return matches;
4514
4552
  }
@@ -4530,12 +4568,13 @@
4530
4568
  }
4531
4569
  case 'array':
4532
4570
  {
4571
+ /** @type {ValueType[]} */
4533
4572
  var array = [];
4534
4573
  var len = value.length;
4535
4574
  var index = 0;
4536
4575
  while (index < len) {
4537
4576
  var entry = convertKeyToValue(value[index]);
4538
- array[index] = entry;
4577
+ setArrayValue(array, index, entry);
4539
4578
  index++;
4540
4579
  }
4541
4580
  return array;
@@ -5295,6 +5334,7 @@
5295
5334
  }
5296
5335
 
5297
5336
  var uniqueID = 0;
5337
+ var activeTransactions = new Set();
5298
5338
  var listeners$1 = ['onabort', 'oncomplete', 'onerror'];
5299
5339
  var readonlyProperties$4 = ['objectStoreNames', 'mode', 'durability', 'db', 'error'];
5300
5340
 
@@ -5426,6 +5466,7 @@
5426
5466
  me.__mode = mode;
5427
5467
  me.__durability = durability;
5428
5468
  me.__db = db;
5469
+ activeTransactions.add(me);
5429
5470
  me.__error = null;
5430
5471
  // @ts-expect-error Part of `ShimEventTarget`
5431
5472
  me.__setOptions({
@@ -5938,6 +5979,7 @@
5938
5979
  me.__errored = true;
5939
5980
  throw e;
5940
5981
  } finally {
5982
+ activeTransactions.delete(me);
5941
5983
  me.__storeHandles = {};
5942
5984
  }
5943
5985
  }
@@ -6144,7 +6186,7 @@
6144
6186
  });
6145
6187
  }
6146
6188
  me.__active = false; // Setting here and in requestsFinished for https://github.com/w3c/IndexedDB/issues/87
6147
-
6189
+ activeTransactions.delete(me);
6148
6190
  if (err !== null) {
6149
6191
  me.__error = err;
6150
6192
  }
@@ -6365,7 +6407,7 @@
6365
6407
  * @returns {void}
6366
6408
  */
6367
6409
  IDBTransaction.__assertActive = function (tx) {
6368
- if (!tx || !tx.__active || tx.__committed) {
6410
+ if (!tx || !tx.__active || !tx.__handlerActive || tx.__committed) {
6369
6411
  throw createDOMException('TransactionInactiveError', 'A request was placed against a transaction which is currently not active, or which is finished');
6370
6412
  }
6371
6413
  };
@@ -6392,6 +6434,9 @@
6392
6434
  Object.defineProperty(IDBTransaction, 'prototype', {
6393
6435
  writable: false
6394
6436
  });
6437
+ /* eslint-enable unicorn/no-top-level-side-effects -- Would be good */
6438
+
6439
+ IDBTransaction.activeTransactions = activeTransactions;
6395
6440
 
6396
6441
  var TypesonPromise = /*#__PURE__*/_createClass(function TypesonPromise(e) {
6397
6442
  _classCallCheck(this, TypesonPromise);
@@ -7778,7 +7823,7 @@
7778
7823
  }
7779
7824
  }
7780
7825
  },
7781
- k = {
7826
+ D = {
7782
7827
  map: {
7783
7828
  test: function test(e) {
7784
7829
  return "Map" === toStringTag(e);
@@ -7791,7 +7836,7 @@
7791
7836
  }
7792
7837
  }
7793
7838
  },
7794
- D = {
7839
+ R = {
7795
7840
  nan: {
7796
7841
  test: function test(e) {
7797
7842
  return Number.isNaN(e);
@@ -8140,8 +8185,8 @@
8140
8185
  revive: function revive() {}
8141
8186
  }
8142
8187
  }],
8143
- ne = [D, M, L, F],
8144
- ce = [Z, Y, re, K, ne, O, z, U, _, B, I, h, N, C].concat("function" == typeof Map ? k : [], "function" == typeof Set ? H : [], "function" == typeof ArrayBuffer ? p : [], "function" == typeof Uint8Array ? X : [], "function" == typeof DataView ? w : [], "undefined" != typeof crypto ? v : [], "undefined" != typeof BigInt ? [m, d] : [], "undefined" != typeof DOMException ? A : [], "undefined" != typeof QuotaExceededError ? W : [], "undefined" != typeof WebTransportError ? te : [], "undefined" != typeof DOMRect ? x : [], "undefined" != typeof DOMPoint ? S : [], "undefined" != typeof DOMQuad ? P : [], "undefined" != typeof DOMMatrix ? T : [], "undefined" != typeof AudioData ? f : [], "undefined" != typeof EncodedAudioChunk ? E : [], "undefined" != typeof EncodedVideoChunk ? j : [], "undefined" != typeof VideoFrame ? ee : []);
8188
+ ne = [R, M, L, F],
8189
+ ce = [Z, Y, re, K, ne, O, z, U, _, B, I, h, N, C].concat("function" == typeof Map ? D : [], "function" == typeof Set ? H : [], "function" == typeof ArrayBuffer ? p : [], "function" == typeof Uint8Array ? X : [], "function" == typeof DataView ? w : [], "undefined" != typeof crypto ? v : [], "undefined" != typeof BigInt ? [m, d] : [], "undefined" != typeof DOMException ? A : [], "undefined" != typeof QuotaExceededError ? W : [], "undefined" != typeof WebTransportError ? te : [], "undefined" != typeof DOMRect ? x : [], "undefined" != typeof DOMPoint ? S : [], "undefined" != typeof DOMQuad ? P : [], "undefined" != typeof DOMMatrix ? T : [], "undefined" != typeof AudioData ? f : [], "undefined" != typeof EncodedAudioChunk ? E : [], "undefined" != typeof EncodedVideoChunk ? j : [], "undefined" != typeof VideoFrame ? ee : []);
8145
8190
  var ue = ce.concat({
8146
8191
  checkDataCloneException: {
8147
8192
  test: function test(e) {
@@ -8158,11 +8203,56 @@
8158
8203
  return false;
8159
8204
  }
8160
8205
  }
8206
+ }),
8207
+ ye = ue.concat({
8208
+ checkSharedArrayBufferException: {
8209
+ test: function test(e) {
8210
+ if ("SharedArrayBuffer" === {}.toString.call(e).slice(8, -1)) throw new DOMException("The object cannot be cloned.", "DataCloneError");
8211
+ return false;
8212
+ }
8213
+ }
8161
8214
  });
8162
8215
 
8163
8216
  // See: https://stackoverflow.com/questions/42170826/categories-for-rejection-by-the-structured-cloning-algorithm
8164
8217
 
8165
- var typeson = new Typeson().register(ue);
8218
+ // Although typeson-registry already has a FileList type in its structured cloning presets,
8219
+ // we need to override it so it works with our tests
8220
+
8221
+ var specSet = ye.flatMap(function (preset) {
8222
+ return Array.isArray(preset) ? preset : [preset];
8223
+ }).find(function (preset) {
8224
+ return preset && !Array.isArray(preset) && 'filelist' in preset;
8225
+ });
8226
+ var origFileList = specSet && !Array.isArray(specSet) && 'filelist' in specSet ? specSet.filelist : undefined;
8227
+ var origTest = origFileList && _typeof(origFileList) === 'object' && 'test' in origFileList && typeof origFileList.test === 'function' ? origFileList.test : undefined;
8228
+ var origRevive = origFileList && _typeof(origFileList) === 'object' && 'revive' in origFileList && typeof origFileList.revive === 'function' ? origFileList.revive : undefined;
8229
+ var customFileList = origFileList ? _objectSpread2(_objectSpread2({}, origFileList), {}, {
8230
+ /**
8231
+ * @param {unknown} x
8232
+ * @param {import('typeson').StateObject} state
8233
+ * @returns {boolean}
8234
+ */
8235
+ test: function test(x, state) {
8236
+ if (typeof FileList !== 'undefined') {
8237
+ return x instanceof FileList;
8238
+ }
8239
+ return typeof origTest === 'function' ? origTest(x, state) : false;
8240
+ },
8241
+ /**
8242
+ * @param {unknown} x
8243
+ * @param {import('typeson').StateObject} state
8244
+ * @returns {unknown}
8245
+ */
8246
+ revive: function revive(x, state) {
8247
+ if (typeof FileList !== 'undefined') {
8248
+ return Reflect.construct(FileList, [x]);
8249
+ }
8250
+ return typeof origRevive === 'function' ? origRevive(x, state) : undefined;
8251
+ }
8252
+ }) : undefined;
8253
+ var typeson = new Typeson().register([ye, customFileList ? {
8254
+ filelist: customFileList
8255
+ } : {}]);
8166
8256
 
8167
8257
  /**
8168
8258
  * @param {(preset: import('typeson-registry').Preset) =>
@@ -8171,7 +8261,7 @@
8171
8261
  */
8172
8262
  function register(func) {
8173
8263
  // eslint-disable-next-line unicorn/no-top-level-assignment-in-function -- Should be one-time cache
8174
- typeson = new Typeson().register(func(ue));
8264
+ typeson = new Typeson().register(func(ye));
8175
8265
  }
8176
8266
 
8177
8267
  /**
@@ -9470,7 +9560,7 @@
9470
9560
  tx.executeSql('INSERT INTO __sys__ VALUES (?,?,?,?,?)', [escapeSQLiteStatement(storeName), encodedKeyPath,
9471
9561
  // For why converting here, see comment and following
9472
9562
  // discussion at:
9473
- // https://github.com/axemclion/IndexedDBShim/issues/313#issuecomment-590086778
9563
+ // https://github.com/indexeddbshim/IndexedDBShim/issues/313#issuecomment-590086778
9474
9564
  Number(store.autoIncrement), '{}', 1], function () {
9475
9565
  delete store.__pendingCreate;
9476
9566
  delete store.__deleted;
@@ -11470,6 +11560,7 @@
11470
11560
  }
11471
11561
  var req = IDBOpenDBRequest.__createInstance();
11472
11562
  var calledDbCreateError = false;
11563
+ var isRevertingSysdb = false;
11473
11564
  if (CFG.autoName && name === '') {
11474
11565
  // eslint-disable-next-line unicorn/no-top-level-assignment-in-function -- Necessary?
11475
11566
  name = 'autoNamedDatabase_' + nameCounter++;
@@ -11496,7 +11587,7 @@
11496
11587
  * @returns {boolean}
11497
11588
  */
11498
11589
  function dbCreateError(tx, err) {
11499
- if (calledDbCreateError) {
11590
+ if (calledDbCreateError || isRevertingSysdb) {
11500
11591
  return false;
11501
11592
  }
11502
11593
  // Defensive cleanup: `pendingVersionChanges.set(name, ...)` (see
@@ -11560,36 +11651,46 @@
11560
11651
  */
11561
11652
  var sysdbFinishedCb = function sysdbFinishedCb(systx, err, cb) {
11562
11653
  if (err) {
11563
- try {
11564
- systx.executeSql('ROLLBACK', [], cb, cb);
11565
- } catch (err) {
11566
- // Browser may fail with expired transaction above so
11567
- // no choice but to manually revert
11654
+ /**
11655
+ * @param {any} [errorToShow]
11656
+ * @returns {void}
11657
+ */
11658
+ var manualRevert = function manualRevert(errorToShow) {
11659
+ /**
11660
+ * @param {string} [msg]
11661
+ * @throws {Error}
11662
+ * @returns {never}
11663
+ */
11664
+ function reportError(msg) {
11665
+ throw new Error('Unable to roll back upgrade transaction!' + (msg || ''));
11666
+ }
11568
11667
  sysdb.transaction(function (systx) {
11569
- /**
11570
- *
11571
- * @param {string} msg
11572
- * @throws {Error}
11573
- * @returns {never}
11574
- */
11575
- function reportError(msg) {
11576
- throw new Error('Unable to roll back upgrade transaction!' + (msg || ''));
11577
- }
11578
-
11579
11668
  // Attempt to revert
11580
11669
  if (oldVersion === 0) {
11581
- systx.executeSql('DELETE FROM dbVersions WHERE "name" = ?', [sqlSafeName], function () {
11582
- // @ts-expect-error Force to work
11583
- cb(reportError); // eslint-disable-line promise/no-callback-in-promise -- Convenient
11584
- },
11585
- // @ts-expect-error Force to work
11586
- reportError);
11670
+ systx.executeSql('DELETE FROM dbVersions WHERE "name" = ?', [sqlSafeName]);
11587
11671
  } else {
11588
- systx.executeSql('UPDATE dbVersions SET "version" = ? WHERE "name" = ?', [oldVersion, sqlSafeName], cb,
11589
- // @ts-expect-error Force to work
11590
- reportError);
11672
+ systx.executeSql('UPDATE dbVersions SET "version" = ? WHERE "name" = ?', [oldVersion, sqlSafeName]);
11591
11673
  }
11674
+ }, function (sqlErr) {
11675
+ isRevertingSysdb = false;
11676
+ cb(sqlErr); // eslint-disable-line promise/no-callback-in-promise -- Convenient
11677
+ }, function () {
11678
+ isRevertingSysdb = false;
11679
+ cb(errorToShow || reportError); // eslint-disable-line promise/no-callback-in-promise -- Convenient
11680
+ });
11681
+ };
11682
+ try {
11683
+ systx.executeSql('ROLLBACK', [], function () {
11684
+ cb(); // eslint-disable-line promise/no-callback-in-promise -- Convenient
11685
+ }, function (tx, sqlErr) {
11686
+ // Browser/Node may fail with expired transaction, so manually revert
11687
+ manualRevert(sqlErr);
11688
+ return false;
11592
11689
  });
11690
+ } catch (e) {
11691
+ // Browser may fail with expired transaction above so
11692
+ // no choice but to manually revert
11693
+ manualRevert(e);
11593
11694
  }
11594
11695
  return;
11595
11696
  }
@@ -11690,6 +11791,7 @@
11690
11791
 
11691
11792
  // eslint-disable-next-line camelcase -- Clear API
11692
11793
  req.transaction.on__preabort = function () {
11794
+ isRevertingSysdb = true;
11693
11795
  pendingVersionChanges.delete(name);
11694
11796
  connection.__upgradeTransaction = null;
11695
11797
  // We ensure any cache is deleted before any request error events fire and try to reopen
@@ -11707,6 +11809,7 @@
11707
11809
  req.__result = undefined;
11708
11810
  req.__done = false;
11709
11811
  connection.close();
11812
+ isRevertingSysdb = true;
11710
11813
  setTimeout(function () {
11711
11814
  var err = createDOMException('AbortError', 'The upgrade transaction was aborted.');
11712
11815
  sysdbFinishedCb(systx, err, function (reportError) {
@@ -11768,7 +11871,26 @@
11768
11871
  }
11769
11872
  sysdbFinishedCb = function sysdbFinishedCb(systx, err, cb) {
11770
11873
  if (err) {
11771
- rollback(err, cb);
11874
+ rollback(err,
11875
+ /**
11876
+ * @param {Error} [reportError]
11877
+ * @returns {void}
11878
+ */
11879
+ function (reportError) {
11880
+ sysdb.transaction(function (systx) {
11881
+ if (oldVersion === 0) {
11882
+ systx.executeSql('DELETE FROM dbVersions WHERE "name" = ?', [sqlSafeName]);
11883
+ } else {
11884
+ systx.executeSql('UPDATE dbVersions SET "version" = ? WHERE "name" = ?', [oldVersion, sqlSafeName]);
11885
+ }
11886
+ }, function (sqlErr) {
11887
+ isRevertingSysdb = false;
11888
+ cb(sqlErr); // eslint-disable-line promise/no-callback-in-promise -- Convenient
11889
+ }, function () {
11890
+ isRevertingSysdb = false;
11891
+ cb(reportError); // eslint-disable-line promise/no-callback-in-promise -- Convenient
11892
+ });
11893
+ });
11772
11894
  } else {
11773
11895
  commit(cb);
11774
11896
  }
@@ -13881,7 +14003,7 @@
13881
14003
  // Ignore Node or other environments
13882
14004
  // Bad non-Chrome Android support
13883
14005
  /Android (?:2|3|4\.[0-3])/.test(navigator.userAgent) && !navigator.userAgent.includes('Chrome') ||
13884
- // Bad non-Safari iOS9 support (see <https://github.com/axemclion/IndexedDBShim/issues/252>)
14006
+ // Bad non-Safari iOS9 support (see <https://github.com/indexeddbshim/IndexedDBShim/issues/252>)
13885
14007
  (!navigator.userAgent.includes('Safari') || navigator.userAgent.includes('Chrome')) &&
13886
14008
  // Exclude genuine Safari: https://stackoverflow.com/a/7768006/271577
13887
14009
  // Detect iOS: https://stackoverflow.com/questions/9038625/detect-if-device-is-ios/9039885#9039885
@@ -13891,8 +14013,8 @@
13891
14013
  if (!CFG.DEFAULT_DB_SIZE) {
13892
14014
  CFG.DEFAULT_DB_SIZE = (
13893
14015
  // Safari currently requires larger size: (We don't need a larger size for Node as node-websql doesn't use this info)
13894
- // https://github.com/axemclion/IndexedDBShim/issues/41
13895
- // https://github.com/axemclion/IndexedDBShim/issues/115
14016
+ // https://github.com/indexeddbshim/IndexedDBShim/issues/41
14017
+ // https://github.com/indexeddbshim/IndexedDBShim/issues/115
13896
14018
  typeof navigator !== 'undefined' &&
13897
14019
  // React Native
13898
14020
  navigator.userAgent && navigator.userAgent.includes('Safari') && !navigator.userAgent.includes('Chrome') ? 25 : 4) * 1024 * 1024;