indexeddbshim 17.2.1 → 17.2.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "indexeddbshim",
3
- "version": "17.2.1",
3
+ "version": "17.2.2",
4
4
  "type": "module",
5
5
  "author": "Parashuram <code@nparashuram.com>",
6
6
  "contributors": [
@@ -48,6 +48,7 @@
48
48
  "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*",
49
49
  "clean-w3cOld": "rimraf D_db.sqlite* D_test* D_database_name* D_idbtransaction*",
50
50
  "copy": "copyup node_modules/core-js-bundle/minified.js 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",
51
+ "fix-permissions": "chmod +x node_modules/npm-run-all/bin/*/index.js",
51
52
  "lint": "eslint .",
52
53
  "eslint": "npm run lint",
53
54
  "sqlite-rebuild": "cd node_modules/sqlite3 && npm i",
package/src/IDBFactory.js CHANGED
@@ -219,6 +219,57 @@ function getLatestCachedWebSQLDB (name) {
219
219
  ];
220
220
  }
221
221
 
222
+ /**
223
+ * A cached WebSQL connection (e.g., from a prior `open()`) can keep the
224
+ * underlying SQLite file handle open even after `IDBDatabase#close()`
225
+ * (which only flags the connection for closing without releasing the
226
+ * handle, to allow instance reuse). On Windows, deleting a file while a
227
+ * handle to it is still open fails with `EBUSY`, so any cached connections
228
+ * for `name` must be actually closed (and evicted, since they're no longer
229
+ * usable) before attempting to remove the file.
230
+ * @param {string} name
231
+ * @param {() => void} cb
232
+ * @returns {void}
233
+ */
234
+ function closeCachedWebSQLConnections (name, cb) {
235
+ if (!Object.hasOwn(websqlDBCache, name)) {
236
+ cb();
237
+ return;
238
+ }
239
+ const dbs = Object.values(websqlDBCache[name]);
240
+ delete websqlDBCache[name];
241
+ let remaining = dbs.length;
242
+ if (remaining === 0) {
243
+ cb();
244
+ return;
245
+ }
246
+ dbs.forEach((db) => {
247
+ const sqliteDB = db._db && db._db._db;
248
+ if (!sqliteDB || !sqliteDB.close) {
249
+ remaining--;
250
+ if (remaining === 0) {
251
+ cb();
252
+ }
253
+ return;
254
+ }
255
+ sqliteDB.close(
256
+ /**
257
+ * @param {Error} err
258
+ * @returns {void}
259
+ */
260
+ (err) => {
261
+ if (err) {
262
+ console.warn('Error closing database connection prior to file removal: ' + err);
263
+ }
264
+ remaining--;
265
+ if (remaining === 0) {
266
+ cb();
267
+ }
268
+ }
269
+ );
270
+ });
271
+ }
272
+
222
273
  /**
223
274
  * @param {OpenDatabase} __openDatabase
224
275
  * @param {string} name
@@ -257,15 +308,17 @@ function cleanupDatabaseResources (__openDatabase, name, escapedDatabaseName, da
257
308
  return;
258
309
  }
259
310
  if (fs && CFG.deleteDatabaseFiles !== false) {
260
- fs.unlink(path.join(CFG.databaseBasePath || '', escapedDatabaseName), (err) => {
261
- if (err && err.code !== 'ENOENT') { // Ignore if file is already deleted
262
- dbError({
263
- code: 0,
264
- message: 'Error removing database file: ' + escapedDatabaseName + ' ' + err
265
- });
266
- return;
267
- }
268
- databaseDeleted();
311
+ closeCachedWebSQLConnections(name, () => {
312
+ fs.unlink(path.join(CFG.databaseBasePath || '', escapedDatabaseName), (err) => {
313
+ if (err && err.code !== 'ENOENT') { // Ignore if file is already deleted
314
+ dbError({
315
+ code: 0,
316
+ message: 'Error removing database file: ' + escapedDatabaseName + ' ' + err
317
+ });
318
+ return;
319
+ }
320
+ databaseDeleted();
321
+ });
269
322
  });
270
323
  return;
271
324
  }
@@ -180,6 +180,19 @@ IDBTransaction.prototype.__transFinishedCb = function (err, cb) {
180
180
  IDBTransaction.prototype.__callTransFinishedCb = function (err, cb) {
181
181
  const me = this;
182
182
  if (me.__transFinishedCb === IDBTransaction.prototype.__transFinishedCb) {
183
+ // Standard (3-argument) `transaction()` implementations (browser WebSQL,
184
+ // `cordova-plugin-sqlite-2`, etc.) never invoke the non-standard 4th
185
+ // callback that installs the real `__transFinishedCb`, so waiting for
186
+ // it here would defer forever. Detect that via arity and, if it's not
187
+ // supported, just call the default (the driver auto-commits on its own).
188
+ const dbConn = me.db && me.db.__db;
189
+ const supportsNonstandardTransCb = Boolean(
190
+ dbConn && typeof dbConn.transaction === 'function' && dbConn.transaction.length >= 4
191
+ );
192
+ if (!supportsNonstandardTransCb) {
193
+ me.__transFinishedCb(err, cb);
194
+ return;
195
+ }
183
196
  setTimeout(() => {
184
197
  me.__callTransFinishedCb(err, cb);
185
198
  }, 0);