@powersync/web 0.0.0-dev-20251129133952 → 0.0.0-dev-20251201150812

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 (56) hide show
  1. package/dist/1807036ae51c10ee4d23.wasm +0 -0
  2. package/dist/{10072fe45f0a8fab0a0e.wasm → 307d8ce2280e3bae09d5.wasm} +0 -0
  3. package/dist/{6e435e51534839845554.wasm → cd8b9e8f4c87bf81c169.wasm} +0 -0
  4. package/dist/e797080f5ed0b5324166.wasm +0 -0
  5. package/dist/index.umd.js +137 -104
  6. package/dist/index.umd.js.map +1 -1
  7. package/dist/worker/SharedSyncImplementation.umd.js +137 -110
  8. package/dist/worker/SharedSyncImplementation.umd.js.map +1 -1
  9. package/dist/worker/WASQLiteDB.umd.js +15 -1
  10. package/dist/worker/WASQLiteDB.umd.js.map +1 -1
  11. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite-async_mjs.umd.js +2 -2
  12. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite-async_mjs.umd.js.map +1 -1
  13. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite_mjs.umd.js +2 -2
  14. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite_mjs.umd.js.map +1 -1
  15. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite-async_mjs.umd.js +2 -2
  16. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite-async_mjs.umd.js.map +1 -1
  17. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js +2 -2
  18. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js.map +1 -1
  19. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js.umd.js +20 -23
  20. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js.umd.js.map +1 -1
  21. package/lib/src/db/PowerSyncDatabase.d.ts +1 -1
  22. package/lib/src/db/PowerSyncDatabase.js +4 -4
  23. package/lib/src/db/adapters/AsyncDatabaseConnection.d.ts +5 -0
  24. package/lib/src/db/adapters/AsyncDatabaseConnection.js +5 -0
  25. package/lib/src/db/adapters/LockedAsyncDatabaseAdapter.d.ts +6 -1
  26. package/lib/src/db/adapters/LockedAsyncDatabaseAdapter.js +20 -5
  27. package/lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.d.ts +5 -1
  28. package/lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js +12 -5
  29. package/lib/src/db/sync/SharedWebStreamingSyncImplementation.d.ts +0 -4
  30. package/lib/src/db/sync/SharedWebStreamingSyncImplementation.js +3 -8
  31. package/lib/src/worker/sync/MockSyncService.d.ts +2 -0
  32. package/lib/src/worker/sync/MockSyncService.js +3 -0
  33. package/lib/src/worker/sync/MockSyncServiceTypes.d.ts +101 -0
  34. package/lib/src/worker/sync/MockSyncServiceTypes.js +1 -0
  35. package/lib/src/worker/sync/MockSyncServiceWorker.d.ts +56 -0
  36. package/lib/src/worker/sync/MockSyncServiceWorker.js +369 -0
  37. package/lib/src/worker/sync/SharedSyncImplementation.d.ts +6 -11
  38. package/lib/src/worker/sync/SharedSyncImplementation.js +73 -64
  39. package/lib/src/worker/sync/SharedSyncImplementation.worker.js +1 -1
  40. package/lib/src/worker/sync/WorkerClient.d.ts +1 -3
  41. package/lib/src/worker/sync/WorkerClient.js +3 -27
  42. package/lib/tsconfig.tsbuildinfo +1 -1
  43. package/package.json +3 -3
  44. package/src/db/PowerSyncDatabase.ts +13 -15
  45. package/src/db/adapters/AsyncDatabaseConnection.ts +5 -0
  46. package/src/db/adapters/LockedAsyncDatabaseAdapter.ts +22 -5
  47. package/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.ts +16 -4
  48. package/src/db/sync/SharedWebStreamingSyncImplementation.ts +5 -11
  49. package/src/worker/sync/MockSyncService.ts +3 -0
  50. package/src/worker/sync/MockSyncServiceTypes.ts +71 -0
  51. package/src/worker/sync/MockSyncServiceWorker.ts +406 -0
  52. package/src/worker/sync/SharedSyncImplementation.ts +85 -78
  53. package/src/worker/sync/SharedSyncImplementation.worker.ts +1 -1
  54. package/src/worker/sync/WorkerClient.ts +4 -30
  55. package/dist/a730f7ca717b02234beb.wasm +0 -0
  56. package/dist/aa2f408d64445fed090e.wasm +0 -0
@@ -3228,12 +3228,26 @@ class SyncStatus {
3228
3228
  return {
3229
3229
  connected: this.connected,
3230
3230
  connecting: this.connecting,
3231
- dataFlow: this.dataFlowStatus,
3231
+ dataFlow: {
3232
+ ...this.dataFlowStatus,
3233
+ uploadError: this.serializeError(this.dataFlowStatus.uploadError),
3234
+ downloadError: this.serializeError(this.dataFlowStatus.downloadError)
3235
+ },
3232
3236
  lastSyncedAt: this.lastSyncedAt,
3233
3237
  hasSynced: this.hasSynced,
3234
3238
  priorityStatusEntries: this.priorityStatusEntries
3235
3239
  };
3236
3240
  }
3241
+ serializeError(error) {
3242
+ if (typeof error == 'undefined') {
3243
+ return undefined;
3244
+ }
3245
+ return {
3246
+ name: error.name,
3247
+ message: error.message,
3248
+ stack: error.stack
3249
+ };
3250
+ }
3237
3251
  static comparePriorities(a, b) {
3238
3252
  return b.priority - a.priority; // Reverse because higher priorities have lower numbers
3239
3253
  }
@@ -17612,6 +17626,11 @@ __webpack_require__.r(__webpack_exports__);
17612
17626
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
17613
17627
  /* harmony export */ ConnectionClosedError: () => (/* binding */ ConnectionClosedError)
17614
17628
  /* harmony export */ });
17629
+ /**
17630
+ * Thrown when an underlying database connection is closed.
17631
+ * This is particularly relevant when worker connections are marked as closed while
17632
+ * operations are still in progress.
17633
+ */
17615
17634
  class ConnectionClosedError extends Error {
17616
17635
  constructor(message) {
17617
17636
  super(message);
@@ -17659,7 +17678,6 @@ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MOD
17659
17678
  _config = null;
17660
17679
  pendingAbortControllers;
17661
17680
  requiresHolds;
17662
- requiresReOpen;
17663
17681
  databaseOpenPromise = null;
17664
17682
  closing;
17665
17683
  closed;
@@ -17672,7 +17690,6 @@ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MOD
17672
17690
  this.closed = false;
17673
17691
  this.closing = false;
17674
17692
  this.requiresHolds = null;
17675
- this.requiresReOpen = false;
17676
17693
  // Set the name if provided. We can query for the name if not available yet
17677
17694
  this.debugMode = options.debugMode ?? false;
17678
17695
  if (this.debugMode) {
@@ -17728,6 +17745,25 @@ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MOD
17728
17745
  */
17729
17746
  this.requiresHolds = this._config.vfs == _wa_sqlite_WASQLiteConnection__WEBPACK_IMPORTED_MODULE_4__.WASQLiteVFS.IDBBatchAtomicVFS;
17730
17747
  }
17748
+ _reOpen() {
17749
+ this.databaseOpenPromise = this.openInternalDB().finally(() => {
17750
+ this.databaseOpenPromise = null;
17751
+ });
17752
+ return this.databaseOpenPromise;
17753
+ }
17754
+ /**
17755
+ * Re-opens the underlying database.
17756
+ * Returns a pending operation if one is already in progress.
17757
+ */
17758
+ async reOpenInternalDB() {
17759
+ if (!this.options.reOpenOnConnectionClosed) {
17760
+ throw new Error(`Cannot re-open underlying database, reOpenOnConnectionClosed is not enabled`);
17761
+ }
17762
+ if (this.databaseOpenPromise) {
17763
+ return this.databaseOpenPromise;
17764
+ }
17765
+ return this._reOpen();
17766
+ }
17731
17767
  async _init() {
17732
17768
  await this.openInternalDB();
17733
17769
  this.iterateListeners((cb) => cb.initialized?.());
@@ -17846,9 +17882,7 @@ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MOD
17846
17882
  if (ex instanceof _AsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_2__.ConnectionClosedError) {
17847
17883
  if (this.options.reOpenOnConnectionClosed && !this.databaseOpenPromise && !this.closing) {
17848
17884
  // Immediately re-open the database. We need to miss as little table updates as possible.
17849
- this.databaseOpenPromise = this.openInternalDB().finally(() => {
17850
- this.databaseOpenPromise = null;
17851
- });
17885
+ this.reOpenInternalDB();
17852
17886
  }
17853
17887
  }
17854
17888
  throw ex;
@@ -17985,19 +18019,22 @@ __webpack_require__.r(__webpack_exports__);
17985
18019
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
17986
18020
  /* harmony export */ WorkerWrappedAsyncDatabaseConnection: () => (/* binding */ WorkerWrappedAsyncDatabaseConnection)
17987
18021
  /* harmony export */ });
17988
- /* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! comlink */ "../../node_modules/comlink/dist/esm/comlink.mjs");
17989
- /* harmony import */ var _AsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AsyncDatabaseConnection */ "./lib/src/db/adapters/AsyncDatabaseConnection.js");
18022
+ /* harmony import */ var _powersync_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @powersync/common */ "../common/dist/bundle.mjs");
18023
+ /* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! comlink */ "../../node_modules/comlink/dist/esm/comlink.mjs");
18024
+ /* harmony import */ var _AsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./AsyncDatabaseConnection */ "./lib/src/db/adapters/AsyncDatabaseConnection.js");
18025
+
17990
18026
 
17991
18027
 
17992
18028
  /**
17993
18029
  * Wraps a provided instance of {@link AsyncDatabaseConnection}, providing necessary proxy
17994
18030
  * functions for worker listeners.
17995
18031
  */
17996
- class WorkerWrappedAsyncDatabaseConnection {
18032
+ class WorkerWrappedAsyncDatabaseConnection extends _powersync_common__WEBPACK_IMPORTED_MODULE_0__.BaseObserver {
17997
18033
  options;
17998
18034
  lockAbortController = new AbortController();
17999
18035
  notifyRemoteClosed;
18000
18036
  constructor(options) {
18037
+ super();
18001
18038
  this.options = options;
18002
18039
  if (options.remoteCanCloseUnexpectedly) {
18003
18040
  this.notifyRemoteClosed = new AbortController();
@@ -18030,17 +18067,20 @@ class WorkerWrappedAsyncDatabaseConnection {
18030
18067
  isAutoCommit() {
18031
18068
  return this.withRemote(() => this.baseConnection.isAutoCommit());
18032
18069
  }
18033
- withRemote(workerPromise) {
18070
+ withRemote(workerPromise, fireActionOnAbort = false) {
18034
18071
  const controller = this.notifyRemoteClosed;
18035
18072
  if (controller) {
18036
18073
  return new Promise((resolve, reject) => {
18037
18074
  if (controller.signal.aborted) {
18038
- reject(new _AsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_0__.ConnectionClosedError('Called operation on closed remote'));
18039
- // Don't run the operation if we're going to reject
18040
- return;
18075
+ reject(new _AsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_1__.ConnectionClosedError('Called operation on closed remote'));
18076
+ if (!fireActionOnAbort) {
18077
+ // Don't run the operation if we're going to reject
18078
+ // We might want to fire-and-forget the operation in some cases (like a close operation)
18079
+ return;
18080
+ }
18041
18081
  }
18042
18082
  function handleAbort() {
18043
- reject(new _AsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_0__.ConnectionClosedError('Remote peer closed with request in flight'));
18083
+ reject(new _AsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_1__.ConnectionClosedError('Remote peer closed with request in flight'));
18044
18084
  }
18045
18085
  function completePromise(action) {
18046
18086
  controller.signal.removeEventListener('abort', handleAbort);
@@ -18094,7 +18134,7 @@ class WorkerWrappedAsyncDatabaseConnection {
18094
18134
  reject(ex);
18095
18135
  }
18096
18136
  }));
18097
- const newPort = await remote[comlink__WEBPACK_IMPORTED_MODULE_1__.createEndpoint]();
18137
+ const newPort = await remote[comlink__WEBPACK_IMPORTED_MODULE_2__.createEndpoint]();
18098
18138
  return { port: newPort, identifier };
18099
18139
  }
18100
18140
  /**
@@ -18102,17 +18142,19 @@ class WorkerWrappedAsyncDatabaseConnection {
18102
18142
  * This can be extended by custom implementations in order to handle proxy events.
18103
18143
  */
18104
18144
  async registerOnTableChange(callback) {
18105
- return this.baseConnection.registerOnTableChange(comlink__WEBPACK_IMPORTED_MODULE_1__.proxy(callback));
18145
+ return this.baseConnection.registerOnTableChange(comlink__WEBPACK_IMPORTED_MODULE_2__.proxy(callback));
18106
18146
  }
18107
18147
  async close() {
18108
18148
  // Abort any pending lock requests.
18109
18149
  this.lockAbortController.abort();
18110
18150
  try {
18111
- await this.withRemote(() => this.baseConnection.close());
18151
+ // fire and forget the close operation
18152
+ await this.withRemote(() => this.baseConnection.close(), true);
18112
18153
  }
18113
18154
  finally {
18114
- this.options.remote[comlink__WEBPACK_IMPORTED_MODULE_1__.releaseProxy]();
18155
+ this.options.remote[comlink__WEBPACK_IMPORTED_MODULE_2__.releaseProxy]();
18115
18156
  this.options.onClose?.();
18157
+ this.iterateListeners((l) => l.closing?.());
18116
18158
  }
18117
18159
  }
18118
18160
  execute(sql, params) {
@@ -18992,14 +19034,25 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
18992
19034
  /**
18993
19035
  * Gets the last client port which we know is safe from unexpected closes.
18994
19036
  */
18995
- get lastWrappedPort() {
18996
- // Find the last port which is protected from close
18997
- for (let i = this.ports.length - 1; i >= 0; i--) {
18998
- if (this.ports[i].isProtectedFromClose && !this.ports[i].isClosing) {
18999
- return this.ports[i];
19037
+ async getLastWrappedPort() {
19038
+ // Find the last port which is not closing
19039
+ return await this.portMutex.runExclusive(() => {
19040
+ for (let i = this.ports.length - 1; i >= 0; i--) {
19041
+ if (!this.ports[i].isClosing) {
19042
+ return this.ports[i];
19043
+ }
19000
19044
  }
19001
- }
19002
- return;
19045
+ return;
19046
+ });
19047
+ }
19048
+ /**
19049
+ * In some very rare cases a specific tab might not respond to requests.
19050
+ * This returns a random port which is not closing.
19051
+ */
19052
+ async getRandomWrappedPort() {
19053
+ return await this.portMutex.runExclusive(() => {
19054
+ return this.ports[Math.floor(Math.random() * this.ports.length)];
19055
+ });
19003
19056
  }
19004
19057
  async waitForStatus(status) {
19005
19058
  return this.withSyncImplementation(async (sync) => {
@@ -19041,39 +19094,45 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19041
19094
  async setParams(params) {
19042
19095
  await this.portMutex.runExclusive(async () => {
19043
19096
  this.collectActiveSubscriptions();
19044
- if (this.syncParams) {
19045
- // Cannot modify already existing sync implementation params
19046
- return;
19047
- }
19048
- // First time setting params
19049
- this.syncParams = params;
19050
- if (params.streamOptions?.flags?.broadcastLogs) {
19051
- this.logger = this.broadCastLogger;
19097
+ });
19098
+ if (this.syncParams) {
19099
+ // Cannot modify already existing sync implementation params
19100
+ return;
19101
+ }
19102
+ // First time setting params
19103
+ this.syncParams = params;
19104
+ if (params.streamOptions?.flags?.broadcastLogs) {
19105
+ this.logger = this.broadCastLogger;
19106
+ }
19107
+ const lockedAdapter = new _db_adapters_LockedAsyncDatabaseAdapter__WEBPACK_IMPORTED_MODULE_4__.LockedAsyncDatabaseAdapter({
19108
+ name: params.dbParams.dbFilename,
19109
+ openConnection: async () => {
19110
+ // Gets a connection from the clients when a new connection is requested.
19111
+ const db = await this.openInternalDB();
19112
+ db.registerListener({
19113
+ closing: () => {
19114
+ lockedAdapter.reOpenInternalDB();
19115
+ }
19116
+ });
19117
+ return db;
19118
+ },
19119
+ logger: this.logger,
19120
+ reOpenOnConnectionClosed: true
19121
+ });
19122
+ this.distributedDB = lockedAdapter;
19123
+ await lockedAdapter.init();
19124
+ lockedAdapter.registerListener({
19125
+ databaseReOpened: () => {
19126
+ // We may have missed some table updates while the database was closed.
19127
+ // We can poke the crud in case we missed any updates.
19128
+ this.connectionManager.syncStreamImplementation?.triggerCrudUpload();
19052
19129
  }
19053
- const lockedAdapter = new _db_adapters_LockedAsyncDatabaseAdapter__WEBPACK_IMPORTED_MODULE_4__.LockedAsyncDatabaseAdapter({
19054
- name: params.dbParams.dbFilename,
19055
- openConnection: async () => {
19056
- // Gets a connection from the clients when a new connection is requested.
19057
- return await this.openInternalDB();
19058
- },
19059
- logger: this.logger,
19060
- reOpenOnConnectionClosed: true
19061
- });
19062
- this.distributedDB = lockedAdapter;
19063
- await lockedAdapter.init();
19064
- lockedAdapter.registerListener({
19065
- databaseReOpened: () => {
19066
- // We may have missed some table updates while the database was closed.
19067
- // We can poke the crud in case we missed any updates.
19068
- this.connectionManager.syncStreamImplementation?.triggerCrudUpload();
19069
- }
19070
- });
19071
- self.onerror = (event) => {
19072
- // Share any uncaught events on the broadcast logger
19073
- this.logger.error('Uncaught exception in PowerSync shared sync worker', event);
19074
- };
19075
- this.iterateListeners((l) => l.initialized?.());
19076
19130
  });
19131
+ self.onerror = (event) => {
19132
+ // Share any uncaught events on the broadcast logger
19133
+ this.logger.error('Uncaught exception in PowerSync shared sync worker', event);
19134
+ };
19135
+ this.iterateListeners((l) => l.initialized?.());
19077
19136
  }
19078
19137
  async dispose() {
19079
19138
  await this.waitForReady();
@@ -19103,7 +19162,6 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19103
19162
  clientProvider: comlink__WEBPACK_IMPORTED_MODULE_7__.wrap(port),
19104
19163
  currentSubscriptions: [],
19105
19164
  closeListeners: [],
19106
- isProtectedFromClose: false,
19107
19165
  isClosing: false
19108
19166
  };
19109
19167
  this.ports.push(portProvider);
@@ -19189,7 +19247,7 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19189
19247
  adapter: new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.SqliteBucketStorage(this.distributedDB, this.logger),
19190
19248
  remote: new _db_sync_WebRemote__WEBPACK_IMPORTED_MODULE_2__.WebRemote({
19191
19249
  invalidateCredentials: async () => {
19192
- const lastPort = this.lastWrappedPort;
19250
+ const lastPort = await this.getLastWrappedPort();
19193
19251
  if (!lastPort) {
19194
19252
  throw new Error('No client port found to invalidate credentials');
19195
19253
  }
@@ -19202,7 +19260,7 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19202
19260
  }
19203
19261
  },
19204
19262
  fetchCredentials: async () => {
19205
- const lastPort = this.lastWrappedPort;
19263
+ const lastPort = await this.getLastWrappedPort();
19206
19264
  if (!lastPort) {
19207
19265
  throw new Error('No client port found to fetch credentials');
19208
19266
  }
@@ -19227,7 +19285,7 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19227
19285
  }
19228
19286
  }, this.logger),
19229
19287
  uploadCrud: async () => {
19230
- const lastPort = this.lastWrappedPort;
19288
+ const lastPort = await this.getLastWrappedPort();
19231
19289
  if (!lastPort) {
19232
19290
  throw new Error('No client port found to upload crud');
19233
19291
  }
@@ -19262,11 +19320,15 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19262
19320
  async openInternalDB() {
19263
19321
  while (true) {
19264
19322
  try {
19265
- const lastClient = this.lastWrappedPort;
19266
- if (!lastClient) {
19323
+ const client = await this.getRandomWrappedPort();
19324
+ if (!client) {
19267
19325
  // Should not really happen in practice
19268
19326
  throw new Error(`Could not open DB connection since no client is connected.`);
19269
19327
  }
19328
+ // Fail-safe timeout for opening a database connection.
19329
+ const timeout = setTimeout(() => {
19330
+ abortController.abort();
19331
+ }, 10_000);
19270
19332
  /**
19271
19333
  * Handle cases where the client might close while opening a connection.
19272
19334
  */
@@ -19275,13 +19337,13 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19275
19337
  abortController.abort();
19276
19338
  };
19277
19339
  const removeCloseListener = () => {
19278
- const index = lastClient.closeListeners.indexOf(closeListener);
19340
+ const index = client.closeListeners.indexOf(closeListener);
19279
19341
  if (index >= 0) {
19280
- lastClient.closeListeners.splice(index, 1);
19342
+ client.closeListeners.splice(index, 1);
19281
19343
  }
19282
19344
  };
19283
- lastClient.closeListeners.push(closeListener);
19284
- const workerPort = await withAbort(() => lastClient.clientProvider.getDBWorkerPort(), abortController.signal).catch((ex) => {
19345
+ client.closeListeners.push(closeListener);
19346
+ const workerPort = await withAbort(() => client.clientProvider.getDBWorkerPort(), abortController.signal).catch((ex) => {
19285
19347
  removeCloseListener();
19286
19348
  throw ex;
19287
19349
  });
@@ -19297,6 +19359,7 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19297
19359
  // We can remove the close listener here since we no longer need it past this point.
19298
19360
  removeCloseListener();
19299
19361
  });
19362
+ clearTimeout(timeout);
19300
19363
  const wrapped = new _db_adapters_WorkerWrappedAsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_5__.WorkerWrappedAsyncDatabaseConnection({
19301
19364
  remote,
19302
19365
  baseConnection: db,
@@ -19305,15 +19368,15 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19305
19368
  // that and ensure pending requests are aborted when the tab is closed.
19306
19369
  remoteCanCloseUnexpectedly: true
19307
19370
  });
19308
- lastClient.closeListeners.push(async () => {
19371
+ client.closeListeners.push(async () => {
19309
19372
  this.logger.info('Aborting open connection because associated tab closed.');
19310
19373
  /**
19311
19374
  * Don't await this close operation. It might never resolve if the tab is closed.
19312
- * We run the close operation first, before marking the remote as closed. This gives the database some chance
19313
- * to close the connection.
19375
+ * We mark the remote as closed first, this will reject any pending requests.
19376
+ * We then call close. The close operation is configured to fire-and-forget, the main promise will reject immediately.
19314
19377
  */
19315
- wrapped.close().catch((ex) => this.logger.warn('error closing database connection', ex));
19316
19378
  wrapped.markRemoteClosed();
19379
+ wrapped.close().catch((ex) => this.logger.warn('error closing database connection', ex));
19317
19380
  });
19318
19381
  return wrapped;
19319
19382
  }
@@ -19331,18 +19394,6 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19331
19394
  this.syncStatus = new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.SyncStatus(status);
19332
19395
  this.ports.forEach((p) => p.clientProvider.statusChanged(status));
19333
19396
  }
19334
- /**
19335
- * A function only used for unit tests which updates the internal
19336
- * sync stream client and all tab client's sync status
19337
- */
19338
- async _testUpdateAllStatuses(status) {
19339
- if (!this.connectionManager.syncStreamImplementation) {
19340
- throw new Error('Cannot update status without a sync stream implementation');
19341
- }
19342
- // Only assigning, don't call listeners for this test
19343
- this.connectionManager.syncStreamImplementation.syncStatus = new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.SyncStatus(status);
19344
- this.updateAllStatuses(status);
19345
- }
19346
19397
  }
19347
19398
  /**
19348
19399
  * Runs the action with an abort controller.
@@ -19402,8 +19453,6 @@ class WorkerClient {
19402
19453
  this.sync = sync;
19403
19454
  this.port = port;
19404
19455
  comlink__WEBPACK_IMPORTED_MODULE_2__.expose(this, this.port);
19405
- }
19406
- async initialize() {
19407
19456
  /**
19408
19457
  * Adds an extra listener which can remove this port
19409
19458
  * from the list of monitored ports.
@@ -19414,15 +19463,6 @@ class WorkerClient {
19414
19463
  await this.removePort();
19415
19464
  }
19416
19465
  });
19417
- /**
19418
- * Keep a reference to the resolved port promise.
19419
- * The init timing is difficult to predict due to the async message passing.
19420
- * We only want to use a port if we are know it's been protected from being closed.
19421
- * The lock based close signal will be added asynchronously. We need to use the
19422
- * added port once the lock is configured.
19423
- */
19424
- this.resolvedPortPromise = this.sync.addPort(this.port);
19425
- this.resolvedPort = await this.resolvedPortPromise;
19426
19466
  }
19427
19467
  async removePort() {
19428
19468
  if (this.resolvedPort) {
@@ -19444,19 +19484,9 @@ class WorkerClient {
19444
19484
  * it can consider the connection to be closed.
19445
19485
  */
19446
19486
  async addLockBasedCloseSignal(name) {
19447
- if (!this.resolvedPortPromise) {
19448
- // The init logic above is actually synchronous, so this should not happen.
19449
- this.sync.broadCastLogger.warn('addLockBasedCloseSignal called before port promise registered');
19450
- }
19451
- else {
19452
- const wrappedPort = await this.resolvedPortPromise;
19453
- /**
19454
- * The client registered a navigator lock. We now can guarantee detecting if the client has closed.
19455
- * E.g. before this point: It's possible some ports might have been created and closed before the
19456
- * lock based close signal is added. We should not trust those ports.
19457
- */
19458
- wrappedPort.isProtectedFromClose = true;
19459
- }
19487
+ // Only add the port once the lock has been obtained on the client.
19488
+ this.resolvedPort = await this.sync.addPort(this.port);
19489
+ // Don't await this lock request
19460
19490
  (0,_shared_navigator__WEBPACK_IMPORTED_MODULE_0__.getNavigatorLocks)().request(name, async () => {
19461
19491
  await this.removePort();
19462
19492
  });
@@ -19488,9 +19518,6 @@ class WorkerClient {
19488
19518
  disconnect() {
19489
19519
  return this.sync.disconnect();
19490
19520
  }
19491
- async _testUpdateAllStatuses(status) {
19492
- return this.sync._testUpdateAllStatuses(status);
19493
- }
19494
19521
  }
19495
19522
 
19496
19523
 
@@ -19672,7 +19699,7 @@ logger.useDefaults();
19672
19699
  const sharedSyncImplementation = new _SharedSyncImplementation__WEBPACK_IMPORTED_MODULE_1__.SharedSyncImplementation();
19673
19700
  _self.onconnect = async function (event) {
19674
19701
  const port = event.ports[0];
19675
- await new _WorkerClient__WEBPACK_IMPORTED_MODULE_2__.WorkerClient(sharedSyncImplementation, port).initialize();
19702
+ new _WorkerClient__WEBPACK_IMPORTED_MODULE_2__.WorkerClient(sharedSyncImplementation, port);
19676
19703
  };
19677
19704
 
19678
19705
  })();