@powersync/web 1.30.0 → 1.31.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 (51) hide show
  1. package/dist/index.umd.js +7194 -1835
  2. package/dist/index.umd.js.map +1 -1
  3. package/dist/worker/SharedSyncImplementation.umd.js +536 -286
  4. package/dist/worker/SharedSyncImplementation.umd.js.map +1 -1
  5. package/dist/worker/WASQLiteDB.umd.js +180 -122
  6. package/dist/worker/WASQLiteDB.umd.js.map +1 -1
  7. package/dist/worker/node_modules_bson_lib_bson_mjs.umd.js +3 -3
  8. package/dist/worker/node_modules_bson_lib_bson_mjs.umd.js.map +1 -1
  9. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite-async_mjs.umd.js +6 -6
  10. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite-async_mjs.umd.js.map +1 -1
  11. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite_mjs.umd.js +6 -6
  12. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite_mjs.umd.js.map +1 -1
  13. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite-async_mjs.umd.js +6 -6
  14. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite-async_mjs.umd.js.map +1 -1
  15. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js +6 -6
  16. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js.map +1 -1
  17. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js.umd.js +9 -9
  18. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js.umd.js.map +1 -1
  19. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js.umd.js +12 -12
  20. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js.umd.js.map +1 -1
  21. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_OPFSCoopSyncVFS_js.umd.js +9 -9
  22. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_OPFSCoopSyncVFS_js.umd.js.map +1 -1
  23. package/lib/package.json +4 -4
  24. package/lib/src/db/PowerSyncDatabase.d.ts +1 -1
  25. package/lib/src/db/PowerSyncDatabase.js +4 -4
  26. package/lib/src/db/adapters/LockedAsyncDatabaseAdapter.d.ts +17 -0
  27. package/lib/src/db/adapters/LockedAsyncDatabaseAdapter.js +109 -19
  28. package/lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.d.ts +5 -1
  29. package/lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js +14 -7
  30. package/lib/src/db/adapters/wa-sqlite/WASQLiteConnection.js +11 -2
  31. package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.d.ts +1 -1
  32. package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.js +2 -2
  33. package/lib/src/db/sync/SharedWebStreamingSyncImplementation.d.ts +2 -5
  34. package/lib/src/db/sync/SharedWebStreamingSyncImplementation.js +51 -35
  35. package/lib/src/worker/sync/SharedSyncImplementation.d.ts +18 -8
  36. package/lib/src/worker/sync/SharedSyncImplementation.js +204 -108
  37. package/lib/src/worker/sync/SharedSyncImplementation.worker.js +1 -1
  38. package/lib/src/worker/sync/WorkerClient.d.ts +4 -5
  39. package/lib/src/worker/sync/WorkerClient.js +7 -9
  40. package/lib/tsconfig.tsbuildinfo +1 -1
  41. package/package.json +5 -5
  42. package/src/db/PowerSyncDatabase.ts +13 -15
  43. package/src/db/adapters/LockedAsyncDatabaseAdapter.ts +126 -25
  44. package/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.ts +18 -6
  45. package/src/db/adapters/wa-sqlite/WASQLiteConnection.ts +11 -3
  46. package/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.ts +3 -3
  47. package/src/db/sync/SharedWebStreamingSyncImplementation.ts +65 -47
  48. package/src/worker/db/WASQLiteDB.worker.ts +0 -1
  49. package/src/worker/sync/SharedSyncImplementation.ts +234 -119
  50. package/src/worker/sync/SharedSyncImplementation.worker.ts +1 -1
  51. package/src/worker/sync/WorkerClient.ts +9 -13
@@ -3,11 +3,11 @@ var sdk_web;
3
3
  /******/ "use strict";
4
4
  /******/ var __webpack_modules__ = ({
5
5
 
6
- /***/ "../../node_modules/@journeyapps/wa-sqlite/src/sqlite-api.js":
6
+ /***/ "../../node_modules/@journeyapps/wa-sqlite/src/sqlite-api.js"
7
7
  /*!*******************************************************************!*\
8
8
  !*** ../../node_modules/@journeyapps/wa-sqlite/src/sqlite-api.js ***!
9
9
  \*******************************************************************/
10
- /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
10
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
11
11
 
12
12
  __webpack_require__.r(__webpack_exports__);
13
13
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
@@ -1147,8 +1147,11 @@ function Factory(Module) {
1147
1147
  // Wait for all pending retry operations to complete. This is
1148
1148
  // normally empty on the first loop iteration.
1149
1149
  if (Module.retryOps.length) {
1150
- await Promise.all(Module.retryOps);
1151
- Module.retryOps = [];
1150
+ try {
1151
+ await Promise.all(Module.retryOps);
1152
+ } finally {
1153
+ Module.retryOps = [];
1154
+ }
1152
1155
  }
1153
1156
 
1154
1157
  rc = await f();
@@ -1193,13 +1196,13 @@ function decl(s) {
1193
1196
  }
1194
1197
 
1195
1198
 
1196
- /***/ }),
1199
+ /***/ },
1197
1200
 
1198
- /***/ "../../node_modules/@journeyapps/wa-sqlite/src/sqlite-constants.js":
1201
+ /***/ "../../node_modules/@journeyapps/wa-sqlite/src/sqlite-constants.js"
1199
1202
  /*!*************************************************************************!*\
1200
1203
  !*** ../../node_modules/@journeyapps/wa-sqlite/src/sqlite-constants.js ***!
1201
1204
  \*************************************************************************/
1202
- /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
1205
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
1203
1206
 
1204
1207
  __webpack_require__.r(__webpack_exports__);
1205
1208
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
@@ -1712,13 +1715,13 @@ const SQLITE_PREPARE_PERSISTENT = 0x01;
1712
1715
  const SQLITE_PREPARE_NORMALIZED = 0x02;
1713
1716
  const SQLITE_PREPARE_NO_VTAB = 0x04;
1714
1717
 
1715
- /***/ }),
1718
+ /***/ },
1716
1719
 
1717
- /***/ "../../node_modules/async-mutex/index.mjs":
1720
+ /***/ "../../node_modules/async-mutex/index.mjs"
1718
1721
  /*!************************************************!*\
1719
1722
  !*** ../../node_modules/async-mutex/index.mjs ***!
1720
1723
  \************************************************/
1721
- /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
1724
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
1722
1725
 
1723
1726
  __webpack_require__.r(__webpack_exports__);
1724
1727
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
@@ -2023,13 +2026,13 @@ function tryAcquire(sync, alreadyAcquiredError = E_ALREADY_LOCKED) {
2023
2026
 
2024
2027
 
2025
2028
 
2026
- /***/ }),
2029
+ /***/ },
2027
2030
 
2028
- /***/ "../../node_modules/comlink/dist/esm/comlink.mjs":
2031
+ /***/ "../../node_modules/comlink/dist/esm/comlink.mjs"
2029
2032
  /*!*******************************************************!*\
2030
2033
  !*** ../../node_modules/comlink/dist/esm/comlink.mjs ***!
2031
2034
  \*******************************************************/
2032
- /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
2035
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
2033
2036
 
2034
2037
  __webpack_require__.r(__webpack_exports__);
2035
2038
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
@@ -2404,13 +2407,13 @@ function generateUUID() {
2404
2407
  //# sourceMappingURL=comlink.mjs.map
2405
2408
 
2406
2409
 
2407
- /***/ }),
2410
+ /***/ },
2408
2411
 
2409
- /***/ "../common/dist/bundle.mjs":
2412
+ /***/ "../common/dist/bundle.mjs"
2410
2413
  /*!*********************************!*\
2411
2414
  !*** ../common/dist/bundle.mjs ***!
2412
2415
  \*********************************/
2413
- /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
2416
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
2414
2417
 
2415
2418
  __webpack_require__.r(__webpack_exports__);
2416
2419
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
@@ -2424,6 +2427,7 @@ __webpack_require__.r(__webpack_exports__);
2424
2427
  /* harmony export */ BaseObserver: () => (/* binding */ BaseObserver),
2425
2428
  /* harmony export */ Column: () => (/* binding */ Column),
2426
2429
  /* harmony export */ ColumnType: () => (/* binding */ ColumnType),
2430
+ /* harmony export */ ConnectionClosedError: () => (/* binding */ ConnectionClosedError),
2427
2431
  /* harmony export */ ConnectionManager: () => (/* binding */ ConnectionManager),
2428
2432
  /* harmony export */ ControlledExecutor: () => (/* binding */ ControlledExecutor),
2429
2433
  /* harmony export */ CrudBatch: () => (/* binding */ CrudBatch),
@@ -3228,12 +3232,30 @@ class SyncStatus {
3228
3232
  return {
3229
3233
  connected: this.connected,
3230
3234
  connecting: this.connecting,
3231
- dataFlow: this.dataFlowStatus,
3235
+ dataFlow: {
3236
+ ...this.dataFlowStatus,
3237
+ uploadError: this.serializeError(this.dataFlowStatus.uploadError),
3238
+ downloadError: this.serializeError(this.dataFlowStatus.downloadError)
3239
+ },
3232
3240
  lastSyncedAt: this.lastSyncedAt,
3233
3241
  hasSynced: this.hasSynced,
3234
3242
  priorityStatusEntries: this.priorityStatusEntries
3235
3243
  };
3236
3244
  }
3245
+ /**
3246
+ * Not all errors are serializable over a MessagePort. E.g. some `DomExceptions` fail to be passed across workers.
3247
+ * This explicitly serializes errors in the SyncStatus.
3248
+ */
3249
+ serializeError(error) {
3250
+ if (typeof error == 'undefined') {
3251
+ return undefined;
3252
+ }
3253
+ return {
3254
+ name: error.name,
3255
+ message: error.message,
3256
+ stack: error.stack
3257
+ };
3258
+ }
3237
3259
  static comparePriorities(a, b) {
3238
3260
  return b.priority - a.priority; // Reverse because higher priorities have lower numbers
3239
3261
  }
@@ -4846,7 +4868,7 @@ var hasRequiredBuffer$1;
4846
4868
  function requireBuffer$1 () {
4847
4869
  if (hasRequiredBuffer$1) return buffer$1;
4848
4870
  hasRequiredBuffer$1 = 1;
4849
- (function (exports) {
4871
+ (function (exports$1) {
4850
4872
 
4851
4873
  const base64 = requireBase64Js();
4852
4874
  const ieee754 = requireIeee754();
@@ -4855,12 +4877,12 @@ function requireBuffer$1 () {
4855
4877
  ? Symbol['for']('nodejs.util.inspect.custom') // eslint-disable-line dot-notation
4856
4878
  : null;
4857
4879
 
4858
- exports.Buffer = Buffer;
4859
- exports.SlowBuffer = SlowBuffer;
4860
- exports.INSPECT_MAX_BYTES = 50;
4880
+ exports$1.Buffer = Buffer;
4881
+ exports$1.SlowBuffer = SlowBuffer;
4882
+ exports$1.INSPECT_MAX_BYTES = 50;
4861
4883
 
4862
4884
  const K_MAX_LENGTH = 0x7fffffff;
4863
- exports.kMaxLength = K_MAX_LENGTH;
4885
+ exports$1.kMaxLength = K_MAX_LENGTH;
4864
4886
 
4865
4887
  /**
4866
4888
  * If `Buffer.TYPED_ARRAY_SUPPORT`:
@@ -5456,7 +5478,7 @@ function requireBuffer$1 () {
5456
5478
 
5457
5479
  Buffer.prototype.inspect = function inspect () {
5458
5480
  let str = '';
5459
- const max = exports.INSPECT_MAX_BYTES;
5481
+ const max = exports$1.INSPECT_MAX_BYTES;
5460
5482
  str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim();
5461
5483
  if (this.length > max) str += ' ... ';
5462
5484
  return '<Buffer ' + str + '>'
@@ -6964,7 +6986,7 @@ var hasRequiredBuffer;
6964
6986
  function requireBuffer () {
6965
6987
  if (hasRequiredBuffer) return buffer;
6966
6988
  hasRequiredBuffer = 1;
6967
- (function (exports) {
6989
+ (function (exports$1) {
6968
6990
 
6969
6991
  var base64 = requireBase64Js();
6970
6992
  var ieee754 = requireIeee754();
@@ -6973,12 +6995,12 @@ function requireBuffer () {
6973
6995
  ? Symbol['for']('nodejs.util.inspect.custom') // eslint-disable-line dot-notation
6974
6996
  : null;
6975
6997
 
6976
- exports.Buffer = Buffer;
6977
- exports.SlowBuffer = SlowBuffer;
6978
- exports.INSPECT_MAX_BYTES = 50;
6998
+ exports$1.Buffer = Buffer;
6999
+ exports$1.SlowBuffer = SlowBuffer;
7000
+ exports$1.INSPECT_MAX_BYTES = 50;
6979
7001
 
6980
7002
  var K_MAX_LENGTH = 0x7fffffff;
6981
- exports.kMaxLength = K_MAX_LENGTH;
7003
+ exports$1.kMaxLength = K_MAX_LENGTH;
6982
7004
 
6983
7005
  /**
6984
7006
  * If `Buffer.TYPED_ARRAY_SUPPORT`:
@@ -7575,7 +7597,7 @@ function requireBuffer () {
7575
7597
 
7576
7598
  Buffer.prototype.inspect = function inspect () {
7577
7599
  var str = '';
7578
- var max = exports.INSPECT_MAX_BYTES;
7600
+ var max = exports$1.INSPECT_MAX_BYTES;
7579
7601
  str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim();
7580
7602
  if (this.length > max) str += ' ... ';
7581
7603
  return '<Buffer ' + str + '>'
@@ -8788,7 +8810,7 @@ var hasRequiredFrames;
8788
8810
  function requireFrames () {
8789
8811
  if (hasRequiredFrames) return Frames;
8790
8812
  hasRequiredFrames = 1;
8791
- (function (exports) {
8813
+ (function (exports$1) {
8792
8814
  /*
8793
8815
  * Copyright 2021-2022 the original author or authors.
8794
8816
  *
@@ -8804,8 +8826,8 @@ function requireFrames () {
8804
8826
  * See the License for the specific language governing permissions and
8805
8827
  * limitations under the License.
8806
8828
  */
8807
- Object.defineProperty(exports, "__esModule", { value: true });
8808
- exports.Frame = exports.Lengths = exports.Flags = exports.FrameTypes = void 0;
8829
+ Object.defineProperty(exports$1, "__esModule", { value: true });
8830
+ exports$1.Frame = exports$1.Lengths = exports$1.Flags = exports$1.FrameTypes = void 0;
8809
8831
  var FrameTypes;
8810
8832
  (function (FrameTypes) {
8811
8833
  FrameTypes[FrameTypes["RESERVED"] = 0] = "RESERVED";
@@ -8824,7 +8846,7 @@ function requireFrames () {
8824
8846
  FrameTypes[FrameTypes["RESUME"] = 13] = "RESUME";
8825
8847
  FrameTypes[FrameTypes["RESUME_OK"] = 14] = "RESUME_OK";
8826
8848
  FrameTypes[FrameTypes["EXT"] = 63] = "EXT";
8827
- })(FrameTypes = exports.FrameTypes || (exports.FrameTypes = {}));
8849
+ })(FrameTypes = exports$1.FrameTypes || (exports$1.FrameTypes = {}));
8828
8850
  (function (Flags) {
8829
8851
  Flags[Flags["NONE"] = 0] = "NONE";
8830
8852
  Flags[Flags["COMPLETE"] = 64] = "COMPLETE";
@@ -8835,7 +8857,7 @@ function requireFrames () {
8835
8857
  Flags[Flags["NEXT"] = 32] = "NEXT";
8836
8858
  Flags[Flags["RESPOND"] = 128] = "RESPOND";
8837
8859
  Flags[Flags["RESUME_ENABLE"] = 128] = "RESUME_ENABLE";
8838
- })(exports.Flags || (exports.Flags = {}));
8860
+ })(exports$1.Flags || (exports$1.Flags = {}));
8839
8861
  (function (Flags) {
8840
8862
  function hasMetadata(flags) {
8841
8863
  return (flags & Flags.METADATA) === Flags.METADATA;
@@ -8869,13 +8891,13 @@ function requireFrames () {
8869
8891
  return (flags & Flags.RESUME_ENABLE) === Flags.RESUME_ENABLE;
8870
8892
  }
8871
8893
  Flags.hasResume = hasResume;
8872
- })(exports.Flags || (exports.Flags = {}));
8894
+ })(exports$1.Flags || (exports$1.Flags = {}));
8873
8895
  (function (Lengths) {
8874
8896
  Lengths[Lengths["FRAME"] = 3] = "FRAME";
8875
8897
  Lengths[Lengths["HEADER"] = 6] = "HEADER";
8876
8898
  Lengths[Lengths["METADATA"] = 3] = "METADATA";
8877
8899
  Lengths[Lengths["REQUEST"] = 3] = "REQUEST";
8878
- })(exports.Lengths || (exports.Lengths = {}));
8900
+ })(exports$1.Lengths || (exports$1.Lengths = {}));
8879
8901
  (function (Frame) {
8880
8902
  function isConnection(frame) {
8881
8903
  return frame.streamId === 0;
@@ -8886,7 +8908,7 @@ function requireFrames () {
8886
8908
  frame.type <= FrameTypes.REQUEST_CHANNEL);
8887
8909
  }
8888
8910
  Frame.isRequest = isRequest;
8889
- })(exports.Frame || (exports.Frame = {}));
8911
+ })(exports$1.Frame || (exports$1.Frame = {}));
8890
8912
 
8891
8913
  } (Frames));
8892
8914
  return Frames;
@@ -8897,7 +8919,7 @@ var hasRequiredCodecs;
8897
8919
  function requireCodecs () {
8898
8920
  if (hasRequiredCodecs) return Codecs;
8899
8921
  hasRequiredCodecs = 1;
8900
- (function (exports) {
8922
+ (function (exports$1) {
8901
8923
  var __generator = (Codecs && Codecs.__generator) || function (thisArg, body) {
8902
8924
  var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
8903
8925
  return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
@@ -8925,22 +8947,22 @@ function requireCodecs () {
8925
8947
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
8926
8948
  }
8927
8949
  };
8928
- Object.defineProperty(exports, "__esModule", { value: true });
8929
- exports.Deserializer = exports.sizeOfFrame = exports.serializeFrame = exports.deserializeFrame = exports.serializeFrameWithLength = exports.deserializeFrames = exports.deserializeFrameWithLength = exports.writeUInt64BE = exports.readUInt64BE = exports.writeUInt24BE = exports.readUInt24BE = exports.MAX_VERSION = exports.MAX_TTL = exports.MAX_STREAM_ID = exports.MAX_RESUME_LENGTH = exports.MAX_REQUEST_N = exports.MAX_REQUEST_COUNT = exports.MAX_MIME_LENGTH = exports.MAX_METADATA_LENGTH = exports.MAX_LIFETIME = exports.MAX_KEEPALIVE = exports.MAX_CODE = exports.FRAME_TYPE_OFFFSET = exports.FLAGS_MASK = void 0;
8950
+ Object.defineProperty(exports$1, "__esModule", { value: true });
8951
+ exports$1.Deserializer = exports$1.sizeOfFrame = exports$1.serializeFrame = exports$1.deserializeFrame = exports$1.serializeFrameWithLength = exports$1.deserializeFrames = exports$1.deserializeFrameWithLength = exports$1.writeUInt64BE = exports$1.readUInt64BE = exports$1.writeUInt24BE = exports$1.readUInt24BE = exports$1.MAX_VERSION = exports$1.MAX_TTL = exports$1.MAX_STREAM_ID = exports$1.MAX_RESUME_LENGTH = exports$1.MAX_REQUEST_N = exports$1.MAX_REQUEST_COUNT = exports$1.MAX_MIME_LENGTH = exports$1.MAX_METADATA_LENGTH = exports$1.MAX_LIFETIME = exports$1.MAX_KEEPALIVE = exports$1.MAX_CODE = exports$1.FRAME_TYPE_OFFFSET = exports$1.FLAGS_MASK = void 0;
8930
8952
  var Frames_1 = requireFrames();
8931
- exports.FLAGS_MASK = 0x3ff; // low 10 bits
8932
- exports.FRAME_TYPE_OFFFSET = 10; // frame type is offset 10 bytes within the uint16 containing type + flags
8933
- exports.MAX_CODE = 0x7fffffff; // uint31
8934
- exports.MAX_KEEPALIVE = 0x7fffffff; // uint31
8935
- exports.MAX_LIFETIME = 0x7fffffff; // uint31
8936
- exports.MAX_METADATA_LENGTH = 0xffffff; // uint24
8937
- exports.MAX_MIME_LENGTH = 0xff; // int8
8938
- exports.MAX_REQUEST_COUNT = 0x7fffffff; // uint31
8939
- exports.MAX_REQUEST_N = 0x7fffffff; // uint31
8940
- exports.MAX_RESUME_LENGTH = 0xffff; // uint16
8941
- exports.MAX_STREAM_ID = 0x7fffffff; // uint31
8942
- exports.MAX_TTL = 0x7fffffff; // uint31
8943
- exports.MAX_VERSION = 0xffff; // uint16
8953
+ exports$1.FLAGS_MASK = 0x3ff; // low 10 bits
8954
+ exports$1.FRAME_TYPE_OFFFSET = 10; // frame type is offset 10 bytes within the uint16 containing type + flags
8955
+ exports$1.MAX_CODE = 0x7fffffff; // uint31
8956
+ exports$1.MAX_KEEPALIVE = 0x7fffffff; // uint31
8957
+ exports$1.MAX_LIFETIME = 0x7fffffff; // uint31
8958
+ exports$1.MAX_METADATA_LENGTH = 0xffffff; // uint24
8959
+ exports$1.MAX_MIME_LENGTH = 0xff; // int8
8960
+ exports$1.MAX_REQUEST_COUNT = 0x7fffffff; // uint31
8961
+ exports$1.MAX_REQUEST_N = 0x7fffffff; // uint31
8962
+ exports$1.MAX_RESUME_LENGTH = 0xffff; // uint16
8963
+ exports$1.MAX_STREAM_ID = 0x7fffffff; // uint31
8964
+ exports$1.MAX_TTL = 0x7fffffff; // uint31
8965
+ exports$1.MAX_VERSION = 0xffff; // uint16
8944
8966
  /**
8945
8967
  * Mimimum value that would overflow bitwise operators (2^32).
8946
8968
  */
@@ -8954,7 +8976,7 @@ function requireCodecs () {
8954
8976
  var val3 = buffer.readUInt8(offset + 2);
8955
8977
  return val1 | val2 | val3;
8956
8978
  }
8957
- exports.readUInt24BE = readUInt24BE;
8979
+ exports$1.readUInt24BE = readUInt24BE;
8958
8980
  /**
8959
8981
  * Writes a uint24 to a buffer starting at the given offset, returning the
8960
8982
  * offset of the next byte.
@@ -8964,7 +8986,7 @@ function requireCodecs () {
8964
8986
  offset = buffer.writeUInt8((value >>> 8) & 0xff, offset); // 2nd byte
8965
8987
  return buffer.writeUInt8(value & 0xff, offset); // 1st byte
8966
8988
  }
8967
- exports.writeUInt24BE = writeUInt24BE;
8989
+ exports$1.writeUInt24BE = writeUInt24BE;
8968
8990
  /**
8969
8991
  * Read a uint64 (technically supports up to 53 bits per JS number
8970
8992
  * representation).
@@ -8974,7 +8996,7 @@ function requireCodecs () {
8974
8996
  var low = buffer.readUInt32BE(offset + 4);
8975
8997
  return high * BITWISE_OVERFLOW + low;
8976
8998
  }
8977
- exports.readUInt64BE = readUInt64BE;
8999
+ exports$1.readUInt64BE = readUInt64BE;
8978
9000
  /**
8979
9001
  * Write a uint64 (technically supports up to 53 bits per JS number
8980
9002
  * representation).
@@ -8985,7 +9007,7 @@ function requireCodecs () {
8985
9007
  offset = buffer.writeUInt32BE(high, offset); // first half of uint64
8986
9008
  return buffer.writeUInt32BE(low, offset); // second half of uint64
8987
9009
  }
8988
- exports.writeUInt64BE = writeUInt64BE;
9010
+ exports$1.writeUInt64BE = writeUInt64BE;
8989
9011
  /**
8990
9012
  * Frame header is:
8991
9013
  * - stream id (uint32 = 4)
@@ -9003,7 +9025,7 @@ function requireCodecs () {
9003
9025
  var frameLength = readUInt24BE(buffer, 0);
9004
9026
  return deserializeFrame(buffer.slice(UINT24_SIZE, UINT24_SIZE + frameLength));
9005
9027
  }
9006
- exports.deserializeFrameWithLength = deserializeFrameWithLength;
9028
+ exports$1.deserializeFrameWithLength = deserializeFrameWithLength;
9007
9029
  /**
9008
9030
  * Given a buffer that may contain zero or more length-prefixed frames followed
9009
9031
  * by zero or more bytes of a (partial) subsequent frame, returns an array of
@@ -9036,7 +9058,7 @@ function requireCodecs () {
9036
9058
  }
9037
9059
  });
9038
9060
  }
9039
- exports.deserializeFrames = deserializeFrames;
9061
+ exports$1.deserializeFrames = deserializeFrames;
9040
9062
  /**
9041
9063
  * Writes a frame to a buffer with a length prefix.
9042
9064
  */
@@ -9047,7 +9069,7 @@ function requireCodecs () {
9047
9069
  buffer.copy(lengthPrefixed, UINT24_SIZE);
9048
9070
  return lengthPrefixed;
9049
9071
  }
9050
- exports.serializeFrameWithLength = serializeFrameWithLength;
9072
+ exports$1.serializeFrameWithLength = serializeFrameWithLength;
9051
9073
  /**
9052
9074
  * Read a frame from the buffer.
9053
9075
  */
@@ -9062,8 +9084,8 @@ function requireCodecs () {
9062
9084
  // );
9063
9085
  var typeAndFlags = buffer.readUInt16BE(offset);
9064
9086
  offset += 2;
9065
- var type = typeAndFlags >>> exports.FRAME_TYPE_OFFFSET; // keep highest 6 bits
9066
- var flags = typeAndFlags & exports.FLAGS_MASK; // keep lowest 10 bits
9087
+ var type = typeAndFlags >>> exports$1.FRAME_TYPE_OFFFSET; // keep highest 6 bits
9088
+ var flags = typeAndFlags & exports$1.FLAGS_MASK; // keep lowest 10 bits
9067
9089
  switch (type) {
9068
9090
  case Frames_1.FrameTypes.SETUP:
9069
9091
  return deserializeSetupFrame(buffer, streamId, flags);
@@ -9100,7 +9122,7 @@ function requireCodecs () {
9100
9122
  // );
9101
9123
  }
9102
9124
  }
9103
- exports.deserializeFrame = deserializeFrame;
9125
+ exports$1.deserializeFrame = deserializeFrame;
9104
9126
  /**
9105
9127
  * Convert the frame to a (binary) buffer.
9106
9128
  */
@@ -9139,7 +9161,7 @@ function requireCodecs () {
9139
9161
  // );
9140
9162
  }
9141
9163
  }
9142
- exports.serializeFrame = serializeFrame;
9164
+ exports$1.serializeFrame = serializeFrame;
9143
9165
  /**
9144
9166
  * Byte size of frame without size prefix
9145
9167
  */
@@ -9178,7 +9200,7 @@ function requireCodecs () {
9178
9200
  // );
9179
9201
  }
9180
9202
  }
9181
- exports.sizeOfFrame = sizeOfFrame;
9203
+ exports$1.sizeOfFrame = sizeOfFrame;
9182
9204
  /**
9183
9205
  * Writes a SETUP frame into a new buffer and returns it.
9184
9206
  *
@@ -9813,7 +9835,7 @@ function requireCodecs () {
9813
9835
  function writeHeader(frame, buffer) {
9814
9836
  var offset = buffer.writeInt32BE(frame.streamId, 0);
9815
9837
  // shift frame to high 6 bits, extract lowest 10 bits from flags
9816
- return buffer.writeUInt16BE((frame.type << exports.FRAME_TYPE_OFFFSET) | (frame.flags & exports.FLAGS_MASK), offset);
9838
+ return buffer.writeUInt16BE((frame.type << exports$1.FRAME_TYPE_OFFFSET) | (frame.flags & exports$1.FLAGS_MASK), offset);
9817
9839
  }
9818
9840
  /**
9819
9841
  * Determine the length of the payload section of a frame. Only applies to
@@ -9894,7 +9916,7 @@ function requireCodecs () {
9894
9916
  };
9895
9917
  return Deserializer;
9896
9918
  }());
9897
- exports.Deserializer = Deserializer;
9919
+ exports$1.Deserializer = Deserializer;
9898
9920
 
9899
9921
  } (Codecs));
9900
9922
  return Codecs;
@@ -10040,7 +10062,7 @@ var hasRequiredErrors;
10040
10062
  function requireErrors () {
10041
10063
  if (hasRequiredErrors) return Errors;
10042
10064
  hasRequiredErrors = 1;
10043
- (function (exports) {
10065
+ (function (exports$1) {
10044
10066
  /*
10045
10067
  * Copyright 2021-2022 the original author or authors.
10046
10068
  *
@@ -10071,8 +10093,8 @@ function requireErrors () {
10071
10093
  d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
10072
10094
  };
10073
10095
  })();
10074
- Object.defineProperty(exports, "__esModule", { value: true });
10075
- exports.ErrorCodes = exports.RSocketError = void 0;
10096
+ Object.defineProperty(exports$1, "__esModule", { value: true });
10097
+ exports$1.ErrorCodes = exports$1.RSocketError = void 0;
10076
10098
  var RSocketError = /** @class */ (function (_super) {
10077
10099
  __extends(RSocketError, _super);
10078
10100
  function RSocketError(code, message) {
@@ -10082,7 +10104,7 @@ function requireErrors () {
10082
10104
  }
10083
10105
  return RSocketError;
10084
10106
  }(Error));
10085
- exports.RSocketError = RSocketError;
10107
+ exports$1.RSocketError = RSocketError;
10086
10108
  (function (ErrorCodes) {
10087
10109
  ErrorCodes[ErrorCodes["RESERVED"] = 0] = "RESERVED";
10088
10110
  ErrorCodes[ErrorCodes["INVALID_SETUP"] = 1] = "INVALID_SETUP";
@@ -10096,7 +10118,7 @@ function requireErrors () {
10096
10118
  ErrorCodes[ErrorCodes["CANCELED"] = 515] = "CANCELED";
10097
10119
  ErrorCodes[ErrorCodes["INVALID"] = 516] = "INVALID";
10098
10120
  ErrorCodes[ErrorCodes["RESERVED_EXTENSION"] = 4294967295] = "RESERVED_EXTENSION";
10099
- })(exports.ErrorCodes || (exports.ErrorCodes = {}));
10121
+ })(exports$1.ErrorCodes || (exports$1.ErrorCodes = {}));
10100
10122
 
10101
10123
  } (Errors));
10102
10124
  return Errors;
@@ -10138,7 +10160,7 @@ var hasRequiredClientServerMultiplexerDemultiplexer;
10138
10160
  function requireClientServerMultiplexerDemultiplexer () {
10139
10161
  if (hasRequiredClientServerMultiplexerDemultiplexer) return ClientServerMultiplexerDemultiplexer;
10140
10162
  hasRequiredClientServerMultiplexerDemultiplexer = 1;
10141
- (function (exports) {
10163
+ (function (exports$1) {
10142
10164
  /*
10143
10165
  * Copyright 2021-2022 the original author or authors.
10144
10166
  *
@@ -10205,8 +10227,8 @@ function requireClientServerMultiplexerDemultiplexer () {
10205
10227
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
10206
10228
  }
10207
10229
  };
10208
- Object.defineProperty(exports, "__esModule", { value: true });
10209
- exports.ResumeOkAwaitingResumableClientServerInputMultiplexerDemultiplexer = exports.ResumableClientServerInputMultiplexerDemultiplexer = exports.ClientServerInputMultiplexerDemultiplexer = exports.StreamIdGenerator = void 0;
10230
+ Object.defineProperty(exports$1, "__esModule", { value: true });
10231
+ exports$1.ResumeOkAwaitingResumableClientServerInputMultiplexerDemultiplexer = exports$1.ResumableClientServerInputMultiplexerDemultiplexer = exports$1.ClientServerInputMultiplexerDemultiplexer = exports$1.StreamIdGenerator = void 0;
10210
10232
  var _1 = requireDist();
10211
10233
  var Deferred_1 = requireDeferred();
10212
10234
  var Errors_1 = requireErrors();
@@ -10229,7 +10251,7 @@ function requireClientServerMultiplexerDemultiplexer () {
10229
10251
  };
10230
10252
  return StreamIdGeneratorImpl;
10231
10253
  }());
10232
- })(exports.StreamIdGenerator || (exports.StreamIdGenerator = {}));
10254
+ })(exports$1.StreamIdGenerator || (exports$1.StreamIdGenerator = {}));
10233
10255
  var ClientServerInputMultiplexerDemultiplexer = /** @class */ (function (_super) {
10234
10256
  __extends(ClientServerInputMultiplexerDemultiplexer, _super);
10235
10257
  function ClientServerInputMultiplexerDemultiplexer(streamIdSupplier, outbound, closeable) {
@@ -10318,7 +10340,7 @@ function requireClientServerMultiplexerDemultiplexer () {
10318
10340
  };
10319
10341
  return ClientServerInputMultiplexerDemultiplexer;
10320
10342
  }(Deferred_1.Deferred));
10321
- exports.ClientServerInputMultiplexerDemultiplexer = ClientServerInputMultiplexerDemultiplexer;
10343
+ exports$1.ClientServerInputMultiplexerDemultiplexer = ClientServerInputMultiplexerDemultiplexer;
10322
10344
  var ResumableClientServerInputMultiplexerDemultiplexer = /** @class */ (function (_super) {
10323
10345
  __extends(ResumableClientServerInputMultiplexerDemultiplexer, _super);
10324
10346
  function ResumableClientServerInputMultiplexerDemultiplexer(streamIdSupplier, outbound, closeable, frameStore, token, sessionStoreOrReconnector, sessionTimeout) {
@@ -10475,7 +10497,7 @@ function requireClientServerMultiplexerDemultiplexer () {
10475
10497
  };
10476
10498
  return ResumableClientServerInputMultiplexerDemultiplexer;
10477
10499
  }(ClientServerInputMultiplexerDemultiplexer));
10478
- exports.ResumableClientServerInputMultiplexerDemultiplexer = ResumableClientServerInputMultiplexerDemultiplexer;
10500
+ exports$1.ResumableClientServerInputMultiplexerDemultiplexer = ResumableClientServerInputMultiplexerDemultiplexer;
10479
10501
  var ResumeOkAwaitingResumableClientServerInputMultiplexerDemultiplexer = /** @class */ (function () {
10480
10502
  function ResumeOkAwaitingResumableClientServerInputMultiplexerDemultiplexer(outbound, closeable, delegate) {
10481
10503
  this.outbound = outbound;
@@ -10532,7 +10554,7 @@ function requireClientServerMultiplexerDemultiplexer () {
10532
10554
  };
10533
10555
  return ResumeOkAwaitingResumableClientServerInputMultiplexerDemultiplexer;
10534
10556
  }());
10535
- exports.ResumeOkAwaitingResumableClientServerInputMultiplexerDemultiplexer = ResumeOkAwaitingResumableClientServerInputMultiplexerDemultiplexer;
10557
+ exports$1.ResumeOkAwaitingResumableClientServerInputMultiplexerDemultiplexer = ResumeOkAwaitingResumableClientServerInputMultiplexerDemultiplexer;
10536
10558
 
10537
10559
  } (ClientServerMultiplexerDemultiplexer));
10538
10560
  return ClientServerMultiplexerDemultiplexer;
@@ -13518,7 +13540,7 @@ var hasRequiredDist;
13518
13540
  function requireDist () {
13519
13541
  if (hasRequiredDist) return dist;
13520
13542
  hasRequiredDist = 1;
13521
- (function (exports) {
13543
+ (function (exports$1) {
13522
13544
  /*
13523
13545
  * Copyright 2021-2022 the original author or authors.
13524
13546
  *
@@ -13541,19 +13563,19 @@ function requireDist () {
13541
13563
  if (k2 === undefined) k2 = k;
13542
13564
  o[k2] = m[k];
13543
13565
  }));
13544
- var __exportStar = (dist && dist.__exportStar) || function(m, exports) {
13545
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
13566
+ var __exportStar = (dist && dist.__exportStar) || function(m, exports$1) {
13567
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports$1, p)) __createBinding(exports$1, m, p);
13546
13568
  };
13547
- Object.defineProperty(exports, "__esModule", { value: true });
13548
- __exportStar(requireCodecs(), exports);
13549
- __exportStar(requireCommon(), exports);
13550
- __exportStar(requireDeferred(), exports);
13551
- __exportStar(requireErrors(), exports);
13552
- __exportStar(requireFrames(), exports);
13553
- __exportStar(requireRSocket(), exports);
13554
- __exportStar(requireRSocketConnector(), exports);
13555
- __exportStar(requireRSocketServer(), exports);
13556
- __exportStar(requireTransport(), exports);
13569
+ Object.defineProperty(exports$1, "__esModule", { value: true });
13570
+ __exportStar(requireCodecs(), exports$1);
13571
+ __exportStar(requireCommon(), exports$1);
13572
+ __exportStar(requireDeferred(), exports$1);
13573
+ __exportStar(requireErrors(), exports$1);
13574
+ __exportStar(requireFrames(), exports$1);
13575
+ __exportStar(requireRSocket(), exports$1);
13576
+ __exportStar(requireRSocketConnector(), exports$1);
13577
+ __exportStar(requireRSocketServer(), exports$1);
13578
+ __exportStar(requireTransport(), exports$1);
13557
13579
 
13558
13580
  } (dist));
13559
13581
  return dist;
@@ -13561,7 +13583,7 @@ function requireDist () {
13561
13583
 
13562
13584
  var distExports = requireDist();
13563
13585
 
13564
- var version = "1.44.0";
13586
+ var version = "1.45.0";
13565
13587
  var PACKAGE = {
13566
13588
  version: version};
13567
13589
 
@@ -17050,6 +17072,27 @@ class SyncDataBatch {
17050
17072
  }
17051
17073
  }
17052
17074
 
17075
+ /**
17076
+ * Thrown when an underlying database connection is closed.
17077
+ * This is particularly relevant when worker connections are marked as closed while
17078
+ * operations are still in progress.
17079
+ */
17080
+ class ConnectionClosedError extends Error {
17081
+ static NAME = 'ConnectionClosedError';
17082
+ static MATCHES(input) {
17083
+ /**
17084
+ * If there are weird package issues which cause multiple versions of classes to be present, the instanceof
17085
+ * check might fail. This also performs a failsafe check.
17086
+ * This might also happen if the Error is serialized and parsed over a bridging channel like a MessagePort.
17087
+ */
17088
+ return (input instanceof ConnectionClosedError || (input instanceof Error && input.name == ConnectionClosedError.NAME));
17089
+ }
17090
+ constructor(message) {
17091
+ super(message);
17092
+ this.name = ConnectionClosedError.NAME;
17093
+ }
17094
+ }
17095
+
17053
17096
  // https://www.sqlite.org/lang_expr.html#castexpr
17054
17097
  var ColumnType;
17055
17098
  (function (ColumnType) {
@@ -17608,20 +17651,20 @@ const parseQuery = (query, parameters) => {
17608
17651
  //# sourceMappingURL=bundle.mjs.map
17609
17652
 
17610
17653
 
17611
- /***/ }),
17654
+ /***/ },
17612
17655
 
17613
- /***/ "./lib/src/db/adapters/LockedAsyncDatabaseAdapter.js":
17656
+ /***/ "./lib/src/db/adapters/LockedAsyncDatabaseAdapter.js"
17614
17657
  /*!***********************************************************!*\
17615
17658
  !*** ./lib/src/db/adapters/LockedAsyncDatabaseAdapter.js ***!
17616
17659
  \***********************************************************/
17617
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
17660
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
17618
17661
 
17619
17662
  __webpack_require__.r(__webpack_exports__);
17620
17663
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
17621
17664
  /* harmony export */ LockedAsyncDatabaseAdapter: () => (/* binding */ LockedAsyncDatabaseAdapter)
17622
17665
  /* harmony export */ });
17623
17666
  /* harmony import */ var _powersync_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @powersync/common */ "../common/dist/bundle.mjs");
17624
- /* harmony import */ var _shared_navigator__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../..//shared/navigator */ "./lib/src/shared/navigator.js");
17667
+ /* harmony import */ var _shared_navigator__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../shared/navigator */ "./lib/src/shared/navigator.js");
17625
17668
  /* harmony import */ var _WorkerWrappedAsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./WorkerWrappedAsyncDatabaseConnection */ "./lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js");
17626
17669
  /* harmony import */ var _wa_sqlite_WASQLiteConnection__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./wa-sqlite/WASQLiteConnection */ "./lib/src/db/adapters/wa-sqlite/WASQLiteConnection.js");
17627
17670
 
@@ -17645,6 +17688,7 @@ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MOD
17645
17688
  _config = null;
17646
17689
  pendingAbortControllers;
17647
17690
  requiresHolds;
17691
+ databaseOpenPromise = null;
17648
17692
  closing;
17649
17693
  closed;
17650
17694
  constructor(options) {
@@ -17694,16 +17738,69 @@ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MOD
17694
17738
  async init() {
17695
17739
  return this.initPromise;
17696
17740
  }
17741
+ async openInternalDB() {
17742
+ /**
17743
+ * Execute opening of the db in a lock in order not to interfere with other operations.
17744
+ */
17745
+ return this._acquireLock(async () => {
17746
+ // Dispose any previous table change listener.
17747
+ this._disposeTableChangeListener?.();
17748
+ this._disposeTableChangeListener = null;
17749
+ this._db?.close().catch((ex) => this.logger.warn(`Error closing database before opening new instance`, ex));
17750
+ const isReOpen = !!this._db;
17751
+ this._db = null;
17752
+ this._db = await this.options.openConnection();
17753
+ await this._db.init();
17754
+ this._config = await this._db.getConfig();
17755
+ await this.registerOnChangeListener(this._db);
17756
+ if (isReOpen) {
17757
+ this.iterateListeners((cb) => cb.databaseReOpened?.());
17758
+ }
17759
+ /**
17760
+ * This is only required for the long-lived shared IndexedDB connections.
17761
+ */
17762
+ this.requiresHolds = this._config.vfs == _wa_sqlite_WASQLiteConnection__WEBPACK_IMPORTED_MODULE_3__.WASQLiteVFS.IDBBatchAtomicVFS;
17763
+ });
17764
+ }
17765
+ _reOpen() {
17766
+ this.databaseOpenPromise = this.openInternalDB().finally(() => {
17767
+ this.databaseOpenPromise = null;
17768
+ });
17769
+ return this.databaseOpenPromise;
17770
+ }
17771
+ /**
17772
+ * Re-opens the underlying database.
17773
+ * Returns a pending operation if one is already in progress.
17774
+ */
17775
+ async reOpenInternalDB() {
17776
+ if (!this.options.reOpenOnConnectionClosed) {
17777
+ throw new Error(`Cannot re-open underlying database, reOpenOnConnectionClosed is not enabled`);
17778
+ }
17779
+ if (this.databaseOpenPromise) {
17780
+ return this.databaseOpenPromise;
17781
+ }
17782
+ return this._reOpen();
17783
+ }
17697
17784
  async _init() {
17698
- this._db = await this.options.openConnection();
17699
- await this._db.init();
17700
- this._config = await this._db.getConfig();
17701
- await this.registerOnChangeListener(this._db);
17702
- this.iterateListeners((cb) => cb.initialized?.());
17703
17785
  /**
17704
- * This is only required for the long-lived shared IndexedDB connections.
17786
+ * For OPFS, we can see this open call sometimes fail due to NoModificationAllowedError.
17787
+ * We should be able to recover from this by re-opening the database.
17705
17788
  */
17706
- this.requiresHolds = this._config.vfs == _wa_sqlite_WASQLiteConnection__WEBPACK_IMPORTED_MODULE_3__.WASQLiteVFS.IDBBatchAtomicVFS;
17789
+ const maxAttempts = 3;
17790
+ for (let count = 0; count < maxAttempts; count++) {
17791
+ try {
17792
+ await this.openInternalDB();
17793
+ break;
17794
+ }
17795
+ catch (ex) {
17796
+ if (count == maxAttempts - 1) {
17797
+ throw ex;
17798
+ }
17799
+ this.logger.warn(`Attempt ${count + 1} of ${maxAttempts} to open database failed, retrying in 1 second...`, ex);
17800
+ await new Promise((resolve) => setTimeout(resolve, 1000));
17801
+ }
17802
+ }
17803
+ this.iterateListeners((cb) => cb.initialized?.());
17707
17804
  }
17708
17805
  getConfiguration() {
17709
17806
  if (!this._config) {
@@ -17750,7 +17847,14 @@ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MOD
17750
17847
  */
17751
17848
  async close() {
17752
17849
  this.closing = true;
17753
- this._disposeTableChangeListener?.();
17850
+ /**
17851
+ * Note that we obtain a reference to the callback to avoid calling the callback with `this` as the context.
17852
+ * This is to avoid Comlink attempting to clone `this` when calling the method.
17853
+ */
17854
+ const dispose = this._disposeTableChangeListener;
17855
+ if (dispose) {
17856
+ dispose();
17857
+ }
17754
17858
  this.pendingAbortControllers.forEach((controller) => controller.abort('Closed'));
17755
17859
  await this.baseDB?.close?.();
17756
17860
  this.closed = true;
@@ -17770,24 +17874,23 @@ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MOD
17770
17874
  async readLock(fn, options) {
17771
17875
  await this.waitForInitialized();
17772
17876
  return this.acquireLock(async () => fn(this.generateDBHelpers({ execute: this._execute, executeRaw: this._executeRaw })), {
17773
- timeoutMs: options?.timeoutMs
17877
+ timeoutMs: options?.timeoutMs ?? this.options.defaultLockTimeoutMs
17774
17878
  });
17775
17879
  }
17776
17880
  async writeLock(fn, options) {
17777
17881
  await this.waitForInitialized();
17778
17882
  return this.acquireLock(async () => fn(this.generateDBHelpers({ execute: this._execute, executeRaw: this._executeRaw })), {
17779
- timeoutMs: options?.timeoutMs
17883
+ timeoutMs: options?.timeoutMs ?? this.options.defaultLockTimeoutMs
17780
17884
  });
17781
17885
  }
17782
- async acquireLock(callback, options) {
17783
- await this.waitForInitialized();
17886
+ async _acquireLock(callback, options) {
17784
17887
  if (this.closing) {
17785
17888
  throw new Error(`Cannot acquire lock, the database is closing`);
17786
17889
  }
17787
17890
  const abortController = new AbortController();
17788
17891
  this.pendingAbortControllers.add(abortController);
17789
17892
  const { timeoutMs } = options ?? {};
17790
- const timoutId = timeoutMs
17893
+ const timeoutId = timeoutMs
17791
17894
  ? setTimeout(() => {
17792
17895
  abortController.abort(`Timeout after ${timeoutMs}ms`);
17793
17896
  this.pendingAbortControllers.delete(abortController);
@@ -17795,19 +17898,49 @@ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MOD
17795
17898
  : null;
17796
17899
  return (0,_shared_navigator__WEBPACK_IMPORTED_MODULE_1__.getNavigatorLocks)().request(`db-lock-${this._dbIdentifier}`, { signal: abortController.signal }, async () => {
17797
17900
  this.pendingAbortControllers.delete(abortController);
17798
- if (timoutId) {
17799
- clearTimeout(timoutId);
17901
+ if (timeoutId) {
17902
+ clearTimeout(timeoutId);
17800
17903
  }
17801
- const holdId = this.requiresHolds ? await this.baseDB.markHold() : null;
17904
+ return await callback();
17905
+ });
17906
+ }
17907
+ async acquireLock(callback, options) {
17908
+ await this.waitForInitialized();
17909
+ // The database is being opened in the background. Wait for it here.
17910
+ if (this.databaseOpenPromise) {
17911
+ await this.databaseOpenPromise;
17912
+ }
17913
+ return this._acquireLock(async () => {
17914
+ let holdId = null;
17802
17915
  try {
17916
+ /**
17917
+ * We can't await this since it uses the same lock as we're in now.
17918
+ * If there is a pending open, this call will throw.
17919
+ * If there is no pending open, but there is also no database - the open
17920
+ * might have failed. We need to re-open the database.
17921
+ */
17922
+ if (this.databaseOpenPromise || !this._db) {
17923
+ throw new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.ConnectionClosedError('Connection is busy re-opening');
17924
+ }
17925
+ holdId = this.requiresHolds ? await this.baseDB.markHold() : null;
17803
17926
  return await callback();
17804
17927
  }
17928
+ catch (ex) {
17929
+ if (_powersync_common__WEBPACK_IMPORTED_MODULE_0__.ConnectionClosedError.MATCHES(ex)) {
17930
+ if (this.options.reOpenOnConnectionClosed && !this.databaseOpenPromise && !this.closing) {
17931
+ // Immediately re-open the database. We need to miss as little table updates as possible.
17932
+ // Note, don't await this since it uses the same lock as we're in now.
17933
+ this.reOpenInternalDB();
17934
+ }
17935
+ }
17936
+ throw ex;
17937
+ }
17805
17938
  finally {
17806
17939
  if (holdId) {
17807
17940
  await this.baseDB.releaseHold(holdId);
17808
17941
  }
17809
17942
  }
17810
- });
17943
+ }, options);
17811
17944
  }
17812
17945
  async readTransaction(fn, options) {
17813
17946
  return this.readLock(this.wrapTransaction(fn));
@@ -17922,29 +18055,32 @@ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MOD
17922
18055
  }
17923
18056
 
17924
18057
 
17925
- /***/ }),
18058
+ /***/ },
17926
18059
 
17927
- /***/ "./lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js":
18060
+ /***/ "./lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js"
17928
18061
  /*!*********************************************************************!*\
17929
18062
  !*** ./lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js ***!
17930
18063
  \*********************************************************************/
17931
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
18064
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
17932
18065
 
17933
18066
  __webpack_require__.r(__webpack_exports__);
17934
18067
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
17935
18068
  /* harmony export */ WorkerWrappedAsyncDatabaseConnection: () => (/* binding */ WorkerWrappedAsyncDatabaseConnection)
17936
18069
  /* harmony export */ });
17937
- /* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! comlink */ "../../node_modules/comlink/dist/esm/comlink.mjs");
18070
+ /* harmony import */ var _powersync_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @powersync/common */ "../common/dist/bundle.mjs");
18071
+ /* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! comlink */ "../../node_modules/comlink/dist/esm/comlink.mjs");
18072
+
17938
18073
 
17939
18074
  /**
17940
18075
  * Wraps a provided instance of {@link AsyncDatabaseConnection}, providing necessary proxy
17941
18076
  * functions for worker listeners.
17942
18077
  */
17943
- class WorkerWrappedAsyncDatabaseConnection {
18078
+ class WorkerWrappedAsyncDatabaseConnection extends _powersync_common__WEBPACK_IMPORTED_MODULE_0__.BaseObserver {
17944
18079
  options;
17945
18080
  lockAbortController = new AbortController();
17946
18081
  notifyRemoteClosed;
17947
18082
  constructor(options) {
18083
+ super();
17948
18084
  this.options = options;
17949
18085
  if (options.remoteCanCloseUnexpectedly) {
17950
18086
  this.notifyRemoteClosed = new AbortController();
@@ -17977,17 +18113,20 @@ class WorkerWrappedAsyncDatabaseConnection {
17977
18113
  isAutoCommit() {
17978
18114
  return this.withRemote(() => this.baseConnection.isAutoCommit());
17979
18115
  }
17980
- withRemote(workerPromise) {
18116
+ withRemote(workerPromise, fireActionOnAbort = false) {
17981
18117
  const controller = this.notifyRemoteClosed;
17982
18118
  if (controller) {
17983
18119
  return new Promise((resolve, reject) => {
17984
18120
  if (controller.signal.aborted) {
17985
- reject(new Error('Called operation on closed remote'));
17986
- // Don't run the operation if we're going to reject
17987
- return;
18121
+ reject(new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.ConnectionClosedError('Called operation on closed remote'));
18122
+ if (!fireActionOnAbort) {
18123
+ // Don't run the operation if we're going to reject
18124
+ // We might want to fire-and-forget the operation in some cases (like a close operation)
18125
+ return;
18126
+ }
17988
18127
  }
17989
18128
  function handleAbort() {
17990
- reject(new Error('Remote peer closed with request in flight'));
18129
+ reject(new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.ConnectionClosedError('Remote peer closed with request in flight'));
17991
18130
  }
17992
18131
  function completePromise(action) {
17993
18132
  controller.signal.removeEventListener('abort', handleAbort);
@@ -18041,7 +18180,7 @@ class WorkerWrappedAsyncDatabaseConnection {
18041
18180
  reject(ex);
18042
18181
  }
18043
18182
  }));
18044
- const newPort = await remote[comlink__WEBPACK_IMPORTED_MODULE_0__.createEndpoint]();
18183
+ const newPort = await remote[comlink__WEBPACK_IMPORTED_MODULE_1__.createEndpoint]();
18045
18184
  return { port: newPort, identifier };
18046
18185
  }
18047
18186
  /**
@@ -18049,17 +18188,19 @@ class WorkerWrappedAsyncDatabaseConnection {
18049
18188
  * This can be extended by custom implementations in order to handle proxy events.
18050
18189
  */
18051
18190
  async registerOnTableChange(callback) {
18052
- return this.baseConnection.registerOnTableChange(comlink__WEBPACK_IMPORTED_MODULE_0__.proxy(callback));
18191
+ return this.baseConnection.registerOnTableChange(comlink__WEBPACK_IMPORTED_MODULE_1__.proxy(callback));
18053
18192
  }
18054
18193
  async close() {
18055
18194
  // Abort any pending lock requests.
18056
18195
  this.lockAbortController.abort();
18057
18196
  try {
18058
- await this.withRemote(() => this.baseConnection.close());
18197
+ // fire and forget the close operation
18198
+ await this.withRemote(() => this.baseConnection.close(), true);
18059
18199
  }
18060
18200
  finally {
18061
- this.options.remote[comlink__WEBPACK_IMPORTED_MODULE_0__.releaseProxy]();
18201
+ this.options.remote[comlink__WEBPACK_IMPORTED_MODULE_1__.releaseProxy]();
18062
18202
  this.options.onClose?.();
18203
+ this.iterateListeners((l) => l.closing?.());
18063
18204
  }
18064
18205
  }
18065
18206
  execute(sql, params) {
@@ -18077,13 +18218,13 @@ class WorkerWrappedAsyncDatabaseConnection {
18077
18218
  }
18078
18219
 
18079
18220
 
18080
- /***/ }),
18221
+ /***/ },
18081
18222
 
18082
- /***/ "./lib/src/db/adapters/wa-sqlite/WASQLiteConnection.js":
18223
+ /***/ "./lib/src/db/adapters/wa-sqlite/WASQLiteConnection.js"
18083
18224
  /*!*************************************************************!*\
18084
18225
  !*** ./lib/src/db/adapters/wa-sqlite/WASQLiteConnection.js ***!
18085
18226
  \*************************************************************/
18086
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
18227
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
18087
18228
 
18088
18229
  __webpack_require__.r(__webpack_exports__);
18089
18230
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
@@ -18182,9 +18323,10 @@ const DEFAULT_MODULE_FACTORIES = {
18182
18323
  }
18183
18324
  // @ts-expect-error The types for this static method are missing upstream
18184
18325
  const { OPFSCoopSyncVFS } = await __webpack_require__.e(/*! import() */ "node_modules_journeyapps_wa-sqlite_src_examples_OPFSCoopSyncVFS_js").then(__webpack_require__.bind(__webpack_require__, /*! @journeyapps/wa-sqlite/src/examples/OPFSCoopSyncVFS.js */ "../../node_modules/@journeyapps/wa-sqlite/src/examples/OPFSCoopSyncVFS.js"));
18326
+ const vfs = await OPFSCoopSyncVFS.create(options.dbFileName, module);
18185
18327
  return {
18186
18328
  module,
18187
- vfs: await OPFSCoopSyncVFS.create(options.dbFileName, module)
18329
+ vfs
18188
18330
  };
18189
18331
  }
18190
18332
  };
@@ -18410,7 +18552,15 @@ class WASqliteConnection extends _powersync_common__WEBPACK_IMPORTED_MODULE_1__.
18410
18552
  }
18411
18553
  async close() {
18412
18554
  this.broadcastChannel?.close();
18413
- await this.sqliteAPI.close(this.dbP);
18555
+ await this.acquireExecuteLock(async () => {
18556
+ /**
18557
+ * Running the close operation inside the same execute mutex prevents errors like:
18558
+ * ```
18559
+ * unable to close due to unfinalized statements or unfinished backups
18560
+ * ```
18561
+ */
18562
+ await this.sqliteAPI.close(this.dbP);
18563
+ });
18414
18564
  }
18415
18565
  async registerOnTableChange(callback) {
18416
18566
  return this.registerListener({
@@ -18492,13 +18642,13 @@ class WASqliteConnection extends _powersync_common__WEBPACK_IMPORTED_MODULE_1__.
18492
18642
  }
18493
18643
 
18494
18644
 
18495
- /***/ }),
18645
+ /***/ },
18496
18646
 
18497
- /***/ "./lib/src/db/sync/WebRemote.js":
18647
+ /***/ "./lib/src/db/sync/WebRemote.js"
18498
18648
  /*!**************************************!*\
18499
18649
  !*** ./lib/src/db/sync/WebRemote.js ***!
18500
18650
  \**************************************/
18501
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
18651
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
18502
18652
 
18503
18653
  __webpack_require__.r(__webpack_exports__);
18504
18654
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
@@ -18552,13 +18702,13 @@ class WebRemote extends _powersync_common__WEBPACK_IMPORTED_MODULE_0__.AbstractR
18552
18702
  }
18553
18703
 
18554
18704
 
18555
- /***/ }),
18705
+ /***/ },
18556
18706
 
18557
- /***/ "./lib/src/db/sync/WebStreamingSyncImplementation.js":
18707
+ /***/ "./lib/src/db/sync/WebStreamingSyncImplementation.js"
18558
18708
  /*!***********************************************************!*\
18559
18709
  !*** ./lib/src/db/sync/WebStreamingSyncImplementation.js ***!
18560
18710
  \***********************************************************/
18561
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
18711
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
18562
18712
 
18563
18713
  __webpack_require__.r(__webpack_exports__);
18564
18714
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
@@ -18586,13 +18736,13 @@ class WebStreamingSyncImplementation extends _powersync_common__WEBPACK_IMPORTED
18586
18736
  }
18587
18737
 
18588
18738
 
18589
- /***/ }),
18739
+ /***/ },
18590
18740
 
18591
- /***/ "./lib/src/db/sync/userAgent.js":
18741
+ /***/ "./lib/src/db/sync/userAgent.js"
18592
18742
  /*!**************************************!*\
18593
18743
  !*** ./lib/src/db/sync/userAgent.js ***!
18594
18744
  \**************************************/
18595
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
18745
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
18596
18746
 
18597
18747
  __webpack_require__.r(__webpack_exports__);
18598
18748
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
@@ -18664,13 +18814,13 @@ function getOsInfo(nav) {
18664
18814
  }
18665
18815
 
18666
18816
 
18667
- /***/ }),
18817
+ /***/ },
18668
18818
 
18669
- /***/ "./lib/src/shared/navigator.js":
18819
+ /***/ "./lib/src/shared/navigator.js"
18670
18820
  /*!*************************************!*\
18671
18821
  !*** ./lib/src/shared/navigator.js ***!
18672
18822
  \*************************************/
18673
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
18823
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
18674
18824
 
18675
18825
  __webpack_require__.r(__webpack_exports__);
18676
18826
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
@@ -18684,13 +18834,13 @@ const getNavigatorLocks = () => {
18684
18834
  };
18685
18835
 
18686
18836
 
18687
- /***/ }),
18837
+ /***/ },
18688
18838
 
18689
- /***/ "./lib/src/worker/sync/BroadcastLogger.js":
18839
+ /***/ "./lib/src/worker/sync/BroadcastLogger.js"
18690
18840
  /*!************************************************!*\
18691
18841
  !*** ./lib/src/worker/sync/BroadcastLogger.js ***!
18692
18842
  \************************************************/
18693
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
18843
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
18694
18844
 
18695
18845
  __webpack_require__.r(__webpack_exports__);
18696
18846
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
@@ -18827,13 +18977,13 @@ class BroadcastLogger {
18827
18977
  }
18828
18978
 
18829
18979
 
18830
- /***/ }),
18980
+ /***/ },
18831
18981
 
18832
- /***/ "./lib/src/worker/sync/SharedSyncImplementation.js":
18982
+ /***/ "./lib/src/worker/sync/SharedSyncImplementation.js"
18833
18983
  /*!*********************************************************!*\
18834
18984
  !*** ./lib/src/worker/sync/SharedSyncImplementation.js ***!
18835
18985
  \*********************************************************/
18836
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
18986
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
18837
18987
 
18838
18988
  __webpack_require__.r(__webpack_exports__);
18839
18989
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
@@ -18842,12 +18992,12 @@ __webpack_require__.r(__webpack_exports__);
18842
18992
  /* harmony export */ });
18843
18993
  /* harmony import */ var _powersync_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @powersync/common */ "../common/dist/bundle.mjs");
18844
18994
  /* harmony import */ var async_mutex__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! async-mutex */ "../../node_modules/async-mutex/index.mjs");
18845
- /* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! comlink */ "../../node_modules/comlink/dist/esm/comlink.mjs");
18846
- /* harmony import */ var _db_sync_WebRemote__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../db/sync/WebRemote */ "./lib/src/db/sync/WebRemote.js");
18847
- /* harmony import */ var _db_sync_WebStreamingSyncImplementation__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../db/sync/WebStreamingSyncImplementation */ "./lib/src/db/sync/WebStreamingSyncImplementation.js");
18848
- /* harmony import */ var _db_adapters_LockedAsyncDatabaseAdapter__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../db/adapters/LockedAsyncDatabaseAdapter */ "./lib/src/db/adapters/LockedAsyncDatabaseAdapter.js");
18849
- /* harmony import */ var _db_adapters_WorkerWrappedAsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../db/adapters/WorkerWrappedAsyncDatabaseConnection */ "./lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js");
18850
- /* harmony import */ var _BroadcastLogger__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./BroadcastLogger */ "./lib/src/worker/sync/BroadcastLogger.js");
18995
+ /* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! comlink */ "../../node_modules/comlink/dist/esm/comlink.mjs");
18996
+ /* harmony import */ var _db_sync_WebRemote__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../db/sync/WebRemote */ "./lib/src/db/sync/WebRemote.js");
18997
+ /* harmony import */ var _db_sync_WebStreamingSyncImplementation__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../db/sync/WebStreamingSyncImplementation */ "./lib/src/db/sync/WebStreamingSyncImplementation.js");
18998
+ /* harmony import */ var _db_adapters_LockedAsyncDatabaseAdapter__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../db/adapters/LockedAsyncDatabaseAdapter */ "./lib/src/db/adapters/LockedAsyncDatabaseAdapter.js");
18999
+ /* harmony import */ var _db_adapters_WorkerWrappedAsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../db/adapters/WorkerWrappedAsyncDatabaseConnection */ "./lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js");
19000
+ /* harmony import */ var _BroadcastLogger__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./BroadcastLogger */ "./lib/src/worker/sync/BroadcastLogger.js");
18851
19001
 
18852
19002
 
18853
19003
 
@@ -18885,7 +19035,6 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
18885
19035
  statusListener;
18886
19036
  fetchCredentialsController;
18887
19037
  uploadDataController;
18888
- dbAdapter;
18889
19038
  syncParams;
18890
19039
  logger;
18891
19040
  lastConnectOptions;
@@ -18894,10 +19043,10 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
18894
19043
  connectionManager;
18895
19044
  syncStatus;
18896
19045
  broadCastLogger;
19046
+ distributedDB;
18897
19047
  constructor() {
18898
19048
  super();
18899
19049
  this.ports = [];
18900
- this.dbAdapter = null;
18901
19050
  this.syncParams = null;
18902
19051
  this.logger = (0,_powersync_common__WEBPACK_IMPORTED_MODULE_0__.createLogger)('shared-sync');
18903
19052
  this.lastConnectOptions = undefined;
@@ -18910,26 +19059,23 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
18910
19059
  }
18911
19060
  });
18912
19061
  });
19062
+ // Should be configured once we get params
19063
+ this.distributedDB = null;
18913
19064
  this.syncStatus = new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.SyncStatus({});
18914
- this.broadCastLogger = new _BroadcastLogger__WEBPACK_IMPORTED_MODULE_6__.BroadcastLogger(this.ports);
19065
+ this.broadCastLogger = new _BroadcastLogger__WEBPACK_IMPORTED_MODULE_7__.BroadcastLogger(this.ports);
18915
19066
  this.connectionManager = new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.ConnectionManager({
18916
19067
  createSyncImplementation: async () => {
18917
- return this.portMutex.runExclusive(async () => {
18918
- await this.waitForReady();
18919
- if (!this.dbAdapter) {
18920
- await this.openInternalDB();
19068
+ await this.waitForReady();
19069
+ const sync = this.generateStreamingImplementation();
19070
+ const onDispose = sync.registerListener({
19071
+ statusChanged: (status) => {
19072
+ this.updateAllStatuses(status.toJSON());
18921
19073
  }
18922
- const sync = this.generateStreamingImplementation();
18923
- const onDispose = sync.registerListener({
18924
- statusChanged: (status) => {
18925
- this.updateAllStatuses(status.toJSON());
18926
- }
18927
- });
18928
- return {
18929
- sync,
18930
- onDispose
18931
- };
18932
19074
  });
19075
+ return {
19076
+ sync,
19077
+ onDispose
19078
+ };
18933
19079
  },
18934
19080
  logger: this.logger
18935
19081
  });
@@ -18940,6 +19086,30 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
18940
19086
  get isConnected() {
18941
19087
  return this.connectionManager.syncStreamImplementation?.isConnected ?? false;
18942
19088
  }
19089
+ /**
19090
+ * Gets the last client port which we know is safe from unexpected closes.
19091
+ */
19092
+ async getLastWrappedPort() {
19093
+ // Find the last port which is not closing
19094
+ return await this.portMutex.runExclusive(() => {
19095
+ for (let i = this.ports.length - 1; i >= 0; i--) {
19096
+ if (!this.ports[i].isClosing) {
19097
+ return this.ports[i];
19098
+ }
19099
+ }
19100
+ return;
19101
+ });
19102
+ }
19103
+ /**
19104
+ * In some very rare cases a specific tab might not respond to requests.
19105
+ * This returns a random port which is not closing.
19106
+ */
19107
+ async getRandomWrappedPort() {
19108
+ return await this.portMutex.runExclusive(() => {
19109
+ const nonClosingPorts = this.ports.filter((p) => !p.isClosing);
19110
+ return nonClosingPorts[Math.floor(Math.random() * nonClosingPorts.length)];
19111
+ });
19112
+ }
18943
19113
  async waitForStatus(status) {
18944
19114
  return this.withSyncImplementation(async (sync) => {
18945
19115
  return sync.waitForStatus(status);
@@ -18980,28 +19150,53 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
18980
19150
  async setParams(params) {
18981
19151
  await this.portMutex.runExclusive(async () => {
18982
19152
  this.collectActiveSubscriptions();
18983
- if (this.syncParams) {
18984
- // Cannot modify already existing sync implementation params
18985
- // But we can ask for a DB adapter, if required, at this point.
18986
- if (!this.dbAdapter) {
18987
- await this.openInternalDB();
18988
- }
18989
- return;
18990
- }
18991
- // First time setting params
18992
- this.syncParams = params;
18993
- if (params.streamOptions?.flags?.broadcastLogs) {
18994
- this.logger = this.broadCastLogger;
18995
- }
18996
- self.onerror = (event) => {
18997
- // Share any uncaught events on the broadcast logger
18998
- this.logger.error('Uncaught exception in PowerSync shared sync worker', event);
18999
- };
19000
- if (!this.dbAdapter) {
19001
- await this.openInternalDB();
19153
+ });
19154
+ if (this.syncParams) {
19155
+ // Cannot modify already existing sync implementation params
19156
+ return;
19157
+ }
19158
+ // First time setting params
19159
+ this.syncParams = params;
19160
+ if (params.streamOptions?.flags?.broadcastLogs) {
19161
+ this.logger = this.broadCastLogger;
19162
+ }
19163
+ const lockedAdapter = new _db_adapters_LockedAsyncDatabaseAdapter__WEBPACK_IMPORTED_MODULE_5__.LockedAsyncDatabaseAdapter({
19164
+ name: params.dbParams.dbFilename,
19165
+ openConnection: async () => {
19166
+ // Gets a connection from the clients when a new connection is requested.
19167
+ const db = await this.openInternalDB();
19168
+ db.registerListener({
19169
+ closing: () => {
19170
+ lockedAdapter.reOpenInternalDB();
19171
+ }
19172
+ });
19173
+ return db;
19174
+ },
19175
+ logger: this.logger,
19176
+ reOpenOnConnectionClosed: true
19177
+ });
19178
+ this.distributedDB = lockedAdapter;
19179
+ await lockedAdapter.init();
19180
+ lockedAdapter.registerListener({
19181
+ databaseReOpened: () => {
19182
+ // We may have missed some table updates while the database was closed.
19183
+ // We can poke the crud in case we missed any updates.
19184
+ this.connectionManager.syncStreamImplementation?.triggerCrudUpload();
19185
+ /**
19186
+ * FIXME or IMPROVE ME
19187
+ * The Rust client implementation stores sync state on the connection level.
19188
+ * Reopening the database causes a state machine error which should cause the
19189
+ * StreamingSyncImplementation to reconnect. It would be nicer if we could trigger
19190
+ * this reconnect earlier.
19191
+ * This reconnect is not required for IndexedDB.
19192
+ */
19002
19193
  }
19003
- this.iterateListeners((l) => l.initialized?.());
19004
19194
  });
19195
+ self.onerror = (event) => {
19196
+ // Share any uncaught events on the broadcast logger
19197
+ this.logger.error('Uncaught exception in PowerSync shared sync worker', event);
19198
+ };
19199
+ this.iterateListeners((l) => l.initialized?.());
19005
19200
  }
19006
19201
  async dispose() {
19007
19202
  await this.waitForReady();
@@ -19028,9 +19223,10 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19028
19223
  return await this.portMutex.runExclusive(() => {
19029
19224
  const portProvider = {
19030
19225
  port,
19031
- clientProvider: comlink__WEBPACK_IMPORTED_MODULE_7__.wrap(port),
19226
+ clientProvider: comlink__WEBPACK_IMPORTED_MODULE_2__.wrap(port),
19032
19227
  currentSubscriptions: [],
19033
- closeListeners: []
19228
+ closeListeners: [],
19229
+ isClosing: false
19034
19230
  };
19035
19231
  this.ports.push(portProvider);
19036
19232
  // Give the newly connected client the latest status
@@ -19046,14 +19242,16 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19046
19242
  * clients.
19047
19243
  */
19048
19244
  async removePort(port) {
19245
+ // Ports might be removed faster than we can process them.
19246
+ port.isClosing = true;
19049
19247
  // Remove the port within a mutex context.
19050
19248
  // Warns if the port is not found. This should not happen in practice.
19051
19249
  // We return early if the port is not found.
19052
- const { trackedPort, shouldReconnect } = await this.portMutex.runExclusive(async () => {
19250
+ return await this.portMutex.runExclusive(async () => {
19053
19251
  const index = this.ports.findIndex((p) => p == port);
19054
19252
  if (index < 0) {
19055
19253
  this.logger.warn(`Could not remove port ${port} since it is not present in active ports.`);
19056
- return {};
19254
+ return () => { };
19057
19255
  }
19058
19256
  const trackedPort = this.ports[index];
19059
19257
  // Remove from the list of active ports
@@ -19067,35 +19265,13 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19067
19265
  abortController.controller.abort(new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.AbortOperation('Closing pending requests after client port is removed'));
19068
19266
  }
19069
19267
  });
19070
- const shouldReconnect = !!this.connectionManager.syncStreamImplementation && this.ports.length > 0;
19071
- return {
19072
- shouldReconnect,
19073
- trackedPort
19074
- };
19075
- });
19076
- if (!trackedPort) {
19077
- // We could not find the port to remove
19078
- return () => { };
19079
- }
19080
- for (const closeListener of trackedPort.closeListeners) {
19081
- await closeListener();
19082
- }
19083
- if (this.dbAdapter && this.dbAdapter == trackedPort.db) {
19084
- // Unconditionally close the connection because the database it's writing to has just been closed.
19085
- // The connection has been closed previously, this might throw. We should be able to ignore it.
19086
- await this.connectionManager
19087
- .disconnect()
19088
- .catch((ex) => this.logger.warn('Error while disconnecting. Will attempt to reconnect.', ex));
19089
- // Clearing the adapter will result in a new one being opened in connect
19090
- this.dbAdapter = null;
19091
- if (shouldReconnect) {
19092
- await this.connectionManager.connect(CONNECTOR_PLACEHOLDER, this.lastConnectOptions ?? {});
19268
+ // Close the worker wrapped database connection, we can't accurately rely on this connection
19269
+ for (const closeListener of trackedPort.closeListeners) {
19270
+ await closeListener();
19093
19271
  }
19094
- }
19095
- // Re-index subscriptions, the subscriptions of the removed port would no longer be considered.
19096
- this.collectActiveSubscriptions();
19097
- // Release proxy
19098
- return () => trackedPort.clientProvider[comlink__WEBPACK_IMPORTED_MODULE_7__.releaseProxy]();
19272
+ this.collectActiveSubscriptions();
19273
+ return () => trackedPort.clientProvider[comlink__WEBPACK_IMPORTED_MODULE_2__.releaseProxy]();
19274
+ });
19099
19275
  }
19100
19276
  triggerCrudUpload() {
19101
19277
  this.withSyncImplementation(async (sync) => {
@@ -19131,11 +19307,14 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19131
19307
  // This should only be called after initialization has completed
19132
19308
  const syncParams = this.syncParams;
19133
19309
  // Create a new StreamingSyncImplementation for each connect call. This is usually done is all SDKs.
19134
- return new _db_sync_WebStreamingSyncImplementation__WEBPACK_IMPORTED_MODULE_3__.WebStreamingSyncImplementation({
19135
- adapter: new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.SqliteBucketStorage(this.dbAdapter, this.logger),
19136
- remote: new _db_sync_WebRemote__WEBPACK_IMPORTED_MODULE_2__.WebRemote({
19310
+ return new _db_sync_WebStreamingSyncImplementation__WEBPACK_IMPORTED_MODULE_4__.WebStreamingSyncImplementation({
19311
+ adapter: new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.SqliteBucketStorage(this.distributedDB, this.logger),
19312
+ remote: new _db_sync_WebRemote__WEBPACK_IMPORTED_MODULE_3__.WebRemote({
19137
19313
  invalidateCredentials: async () => {
19138
- const lastPort = this.ports[this.ports.length - 1];
19314
+ const lastPort = await this.getLastWrappedPort();
19315
+ if (!lastPort) {
19316
+ throw new Error('No client port found to invalidate credentials');
19317
+ }
19139
19318
  try {
19140
19319
  this.logger.log('calling the last port client provider to invalidate credentials');
19141
19320
  lastPort.clientProvider.invalidateCredentials();
@@ -19145,7 +19324,10 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19145
19324
  }
19146
19325
  },
19147
19326
  fetchCredentials: async () => {
19148
- const lastPort = this.ports[this.ports.length - 1];
19327
+ const lastPort = await this.getLastWrappedPort();
19328
+ if (!lastPort) {
19329
+ throw new Error('No client port found to fetch credentials');
19330
+ }
19149
19331
  return new Promise(async (resolve, reject) => {
19150
19332
  const abortController = new AbortController();
19151
19333
  this.fetchCredentialsController = {
@@ -19167,7 +19349,10 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19167
19349
  }
19168
19350
  }, this.logger),
19169
19351
  uploadCrud: async () => {
19170
- const lastPort = this.ports[this.ports.length - 1];
19352
+ const lastPort = await this.getLastWrappedPort();
19353
+ if (!lastPort) {
19354
+ throw new Error('No client port found to upload crud');
19355
+ }
19171
19356
  return new Promise(async (resolve, reject) => {
19172
19357
  const abortController = new AbortController();
19173
19358
  this.uploadDataController = {
@@ -19193,38 +19378,81 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19193
19378
  logger: this.logger
19194
19379
  });
19195
19380
  }
19381
+ /**
19382
+ * Opens a worker wrapped database connection. Using the last connected client port.
19383
+ */
19196
19384
  async openInternalDB() {
19197
- const lastClient = this.ports[this.ports.length - 1];
19198
- if (!lastClient) {
19385
+ const client = await this.getRandomWrappedPort();
19386
+ if (!client) {
19199
19387
  // Should not really happen in practice
19200
19388
  throw new Error(`Could not open DB connection since no client is connected.`);
19201
19389
  }
19202
- const workerPort = await lastClient.clientProvider.getDBWorkerPort();
19203
- const remote = comlink__WEBPACK_IMPORTED_MODULE_7__.wrap(workerPort);
19390
+ // Fail-safe timeout for opening a database connection.
19391
+ const timeout = setTimeout(() => {
19392
+ abortController.abort();
19393
+ }, 10_000);
19394
+ /**
19395
+ * Handle cases where the client might close while opening a connection.
19396
+ */
19397
+ const abortController = new AbortController();
19398
+ const closeListener = () => {
19399
+ abortController.abort();
19400
+ };
19401
+ const removeCloseListener = () => {
19402
+ const index = client.closeListeners.indexOf(closeListener);
19403
+ if (index >= 0) {
19404
+ client.closeListeners.splice(index, 1);
19405
+ }
19406
+ };
19407
+ client.closeListeners.push(closeListener);
19408
+ const workerPort = await withAbort({
19409
+ action: () => client.clientProvider.getDBWorkerPort(),
19410
+ signal: abortController.signal,
19411
+ cleanupOnAbort: (port) => {
19412
+ port.close();
19413
+ }
19414
+ }).catch((ex) => {
19415
+ removeCloseListener();
19416
+ throw ex;
19417
+ });
19418
+ const remote = comlink__WEBPACK_IMPORTED_MODULE_2__.wrap(workerPort);
19204
19419
  const identifier = this.syncParams.dbParams.dbFilename;
19205
- const db = await remote(this.syncParams.dbParams);
19206
- const locked = new _db_adapters_LockedAsyncDatabaseAdapter__WEBPACK_IMPORTED_MODULE_4__.LockedAsyncDatabaseAdapter({
19207
- name: identifier,
19208
- openConnection: async () => {
19209
- const wrapped = new _db_adapters_WorkerWrappedAsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_5__.WorkerWrappedAsyncDatabaseConnection({
19210
- remote,
19211
- baseConnection: db,
19212
- identifier,
19213
- // It's possible for this worker to outlive the client hosting the database for us. We need to be prepared for
19214
- // that and ensure pending requests are aborted when the tab is closed.
19215
- remoteCanCloseUnexpectedly: true
19216
- });
19217
- lastClient.closeListeners.push(async () => {
19218
- this.logger.info('Aborting open connection because associated tab closed.');
19219
- await wrapped.close().catch((ex) => this.logger.warn('error closing database connection', ex));
19220
- wrapped.markRemoteClosed();
19221
- });
19222
- return wrapped;
19223
- },
19224
- logger: this.logger
19420
+ /**
19421
+ * The open could fail if the tab is closed while we're busy opening the database.
19422
+ * This operation is typically executed inside an exclusive portMutex lock.
19423
+ * We typically execute the closeListeners using the portMutex in a different context.
19424
+ * We can't rely on the closeListeners to abort the operation if the tab is closed.
19425
+ */
19426
+ const db = await withAbort({
19427
+ action: () => remote(this.syncParams.dbParams),
19428
+ signal: abortController.signal,
19429
+ cleanupOnAbort: (db) => {
19430
+ db.close();
19431
+ }
19432
+ }).finally(() => {
19433
+ // We can remove the close listener here since we no longer need it past this point.
19434
+ removeCloseListener();
19435
+ });
19436
+ clearTimeout(timeout);
19437
+ const wrapped = new _db_adapters_WorkerWrappedAsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_6__.WorkerWrappedAsyncDatabaseConnection({
19438
+ remote,
19439
+ baseConnection: db,
19440
+ identifier,
19441
+ // It's possible for this worker to outlive the client hosting the database for us. We need to be prepared for
19442
+ // that and ensure pending requests are aborted when the tab is closed.
19443
+ remoteCanCloseUnexpectedly: true
19444
+ });
19445
+ client.closeListeners.push(async () => {
19446
+ this.logger.info('Aborting open connection because associated tab closed.');
19447
+ /**
19448
+ * Don't await this close operation. It might never resolve if the tab is closed.
19449
+ * We mark the remote as closed first, this will reject any pending requests.
19450
+ * We then call close. The close operation is configured to fire-and-forget, the main promise will reject immediately.
19451
+ */
19452
+ wrapped.markRemoteClosed();
19453
+ wrapped.close().catch((ex) => this.logger.warn('error closing database connection', ex));
19225
19454
  });
19226
- await locked.init();
19227
- this.dbAdapter = lastClient.db = locked;
19455
+ return wrapped;
19228
19456
  }
19229
19457
  /**
19230
19458
  * A method to update the all shared statuses for each
@@ -19234,36 +19462,54 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19234
19462
  this.syncStatus = new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.SyncStatus(status);
19235
19463
  this.ports.forEach((p) => p.clientProvider.statusChanged(status));
19236
19464
  }
19237
- /**
19238
- * A function only used for unit tests which updates the internal
19239
- * sync stream client and all tab client's sync status
19240
- */
19241
- async _testUpdateAllStatuses(status) {
19242
- if (!this.connectionManager.syncStreamImplementation) {
19243
- throw new Error('Cannot update status without a sync stream implementation');
19465
+ }
19466
+ /**
19467
+ * Runs the action with an abort controller.
19468
+ */
19469
+ function withAbort(options) {
19470
+ const { action, signal, cleanupOnAbort } = options;
19471
+ return new Promise((resolve, reject) => {
19472
+ if (signal.aborted) {
19473
+ reject(new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.AbortOperation('Operation aborted by abort controller'));
19474
+ return;
19244
19475
  }
19245
- // Only assigning, don't call listeners for this test
19246
- this.connectionManager.syncStreamImplementation.syncStatus = new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.SyncStatus(status);
19247
- this.updateAllStatuses(status);
19248
- }
19476
+ function handleAbort() {
19477
+ signal.removeEventListener('abort', handleAbort);
19478
+ reject(new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.AbortOperation('Operation aborted by abort controller'));
19479
+ }
19480
+ signal.addEventListener('abort', handleAbort, { once: true });
19481
+ function completePromise(action) {
19482
+ signal.removeEventListener('abort', handleAbort);
19483
+ action();
19484
+ }
19485
+ action()
19486
+ .then((data) => {
19487
+ // We already rejected due to the abort, allow for cleanup
19488
+ if (signal.aborted) {
19489
+ return completePromise(() => cleanupOnAbort?.(data));
19490
+ }
19491
+ completePromise(() => resolve(data));
19492
+ })
19493
+ .catch((e) => completePromise(() => reject(e)));
19494
+ });
19249
19495
  }
19250
19496
 
19251
19497
 
19252
- /***/ }),
19498
+ /***/ },
19253
19499
 
19254
- /***/ "./lib/src/worker/sync/WorkerClient.js":
19500
+ /***/ "./lib/src/worker/sync/WorkerClient.js"
19255
19501
  /*!*********************************************!*\
19256
19502
  !*** ./lib/src/worker/sync/WorkerClient.js ***!
19257
19503
  \*********************************************/
19258
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
19504
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
19259
19505
 
19260
19506
  __webpack_require__.r(__webpack_exports__);
19261
19507
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
19262
19508
  /* harmony export */ WorkerClient: () => (/* binding */ WorkerClient)
19263
19509
  /* harmony export */ });
19264
- /* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! comlink */ "../../node_modules/comlink/dist/esm/comlink.mjs");
19265
- /* harmony import */ var _SharedSyncImplementation__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./SharedSyncImplementation */ "./lib/src/worker/sync/SharedSyncImplementation.js");
19510
+ /* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! comlink */ "../../node_modules/comlink/dist/esm/comlink.mjs");
19266
19511
  /* harmony import */ var _shared_navigator__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../shared/navigator */ "./lib/src/shared/navigator.js");
19512
+ /* harmony import */ var _SharedSyncImplementation__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./SharedSyncImplementation */ "./lib/src/worker/sync/SharedSyncImplementation.js");
19267
19513
 
19268
19514
 
19269
19515
 
@@ -19277,23 +19523,21 @@ class WorkerClient {
19277
19523
  sync;
19278
19524
  port;
19279
19525
  resolvedPort = null;
19526
+ resolvedPortPromise = null;
19280
19527
  constructor(sync, port) {
19281
19528
  this.sync = sync;
19282
19529
  this.port = port;
19283
- }
19284
- async initialize() {
19530
+ comlink__WEBPACK_IMPORTED_MODULE_0__.expose(this, this.port);
19285
19531
  /**
19286
19532
  * Adds an extra listener which can remove this port
19287
19533
  * from the list of monitored ports.
19288
19534
  */
19289
19535
  this.port.addEventListener('message', async (event) => {
19290
19536
  const payload = event.data;
19291
- if (payload?.event == _SharedSyncImplementation__WEBPACK_IMPORTED_MODULE_0__.SharedSyncClientEvent.CLOSE_CLIENT) {
19537
+ if (payload?.event == _SharedSyncImplementation__WEBPACK_IMPORTED_MODULE_2__.SharedSyncClientEvent.CLOSE_CLIENT) {
19292
19538
  await this.removePort();
19293
19539
  }
19294
19540
  });
19295
- this.resolvedPort = await this.sync.addPort(this.port);
19296
- comlink__WEBPACK_IMPORTED_MODULE_2__.expose(this, this.port);
19297
19541
  }
19298
19542
  async removePort() {
19299
19543
  if (this.resolvedPort) {
@@ -19302,7 +19546,7 @@ class WorkerClient {
19302
19546
  const release = await this.sync.removePort(resolved);
19303
19547
  this.resolvedPort = null;
19304
19548
  this.port.postMessage({
19305
- event: _SharedSyncImplementation__WEBPACK_IMPORTED_MODULE_0__.SharedSyncClientEvent.CLOSE_ACK,
19549
+ event: _SharedSyncImplementation__WEBPACK_IMPORTED_MODULE_2__.SharedSyncClientEvent.CLOSE_ACK,
19306
19550
  data: {}
19307
19551
  });
19308
19552
  release?.();
@@ -19314,7 +19558,10 @@ class WorkerClient {
19314
19558
  * When the client tab is closed, its lock will be returned. So when the shared worker attempts to acquire the lock,
19315
19559
  * it can consider the connection to be closed.
19316
19560
  */
19317
- addLockBasedCloseSignal(name) {
19561
+ async addLockBasedCloseSignal(name) {
19562
+ // Only add the port once the lock has been obtained on the client.
19563
+ this.resolvedPort = await this.sync.addPort(this.port);
19564
+ // Don't await this lock request
19318
19565
  (0,_shared_navigator__WEBPACK_IMPORTED_MODULE_1__.getNavigatorLocks)().request(name, async () => {
19319
19566
  await this.removePort();
19320
19567
  });
@@ -19346,13 +19593,10 @@ class WorkerClient {
19346
19593
  disconnect() {
19347
19594
  return this.sync.disconnect();
19348
19595
  }
19349
- async _testUpdateAllStatuses(status) {
19350
- return this.sync._testUpdateAllStatuses(status);
19351
- }
19352
19596
  }
19353
19597
 
19354
19598
 
19355
- /***/ })
19599
+ /***/ }
19356
19600
 
19357
19601
  /******/ });
19358
19602
  /************************************************************************/
@@ -19366,6 +19610,12 @@ class WorkerClient {
19366
19610
  /******/ if (cachedModule !== undefined) {
19367
19611
  /******/ return cachedModule.exports;
19368
19612
  /******/ }
19613
+ /******/ // Check if module exists (development only)
19614
+ /******/ if (__webpack_modules__[moduleId] === undefined) {
19615
+ /******/ var e = new Error("Cannot find module '" + moduleId + "'");
19616
+ /******/ e.code = 'MODULE_NOT_FOUND';
19617
+ /******/ throw e;
19618
+ /******/ }
19369
19619
  /******/ // Create a new module (and put it into the cache)
19370
19620
  /******/ var module = __webpack_module_cache__[moduleId] = {
19371
19621
  /******/ // no module.id needed
@@ -19530,7 +19780,7 @@ logger.useDefaults();
19530
19780
  const sharedSyncImplementation = new _SharedSyncImplementation__WEBPACK_IMPORTED_MODULE_1__.SharedSyncImplementation();
19531
19781
  _self.onconnect = async function (event) {
19532
19782
  const port = event.ports[0];
19533
- await new _WorkerClient__WEBPACK_IMPORTED_MODULE_2__.WorkerClient(sharedSyncImplementation, port).initialize();
19783
+ new _WorkerClient__WEBPACK_IMPORTED_MODULE_2__.WorkerClient(sharedSyncImplementation, port);
19534
19784
  };
19535
19785
 
19536
19786
  })();