@powersync/web 1.10.2 → 1.12.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 (26) hide show
  1. package/README.md +10 -1
  2. package/bin/powersync.js +43 -0
  3. package/dist/24cd027f23123a1360de.wasm +0 -0
  4. package/dist/_journeyapps_wa-sqlite-_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js-async-mutex-c-3cff7d0.index.umd.js +325 -0
  5. package/dist/_journeyapps_wa-sqlite-_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js-async-mutex-c-3cff7d0.index.umd.js.map +1 -0
  6. package/dist/_journeyapps_wa-sqlite-_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js-async-mutex-c-3cff7d1.index.umd.js +325 -0
  7. package/dist/_journeyapps_wa-sqlite-_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js-async-mutex-c-3cff7d1.index.umd.js.map +1 -0
  8. package/dist/index.umd.js +58 -177
  9. package/dist/index.umd.js.map +1 -1
  10. package/dist/worker/SharedSyncImplementation.umd.js +232 -233
  11. package/dist/worker/SharedSyncImplementation.umd.js.map +1 -1
  12. package/dist/worker/WASQLiteDB.umd.js +223 -233
  13. package/dist/worker/WASQLiteDB.umd.js.map +1 -1
  14. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite-async_mjs.umd.js +2 -132
  15. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite-async_mjs.umd.js.map +1 -1
  16. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js.umd.js +1707 -1372
  17. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js.umd.js.map +1 -1
  18. package/lib/package.json +8 -3
  19. package/lib/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.d.ts +2 -1
  20. package/lib/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.js +4 -1
  21. package/lib/src/db/adapters/web-sql-flags.d.ts +9 -0
  22. package/lib/src/db/adapters/web-sql-flags.js +5 -0
  23. package/lib/src/shared/open-db.js +36 -35
  24. package/lib/tsconfig.tsbuildinfo +1 -1
  25. package/package.json +8 -3
  26. package/dist/5fe5ed837a91c836c24f.wasm +0 -0
@@ -359,6 +359,7 @@ class WASQLiteDBAdapter extends _powersync_common__WEBPACK_IMPORTED_MODULE_0__.B
359
359
  if (!enableMultiTabs) {
360
360
  this.logger.warn('Multiple tabs are not enabled in this browser');
361
361
  }
362
+ const tempStoreQuery = `PRAGMA temp_store = ${this.options.temporaryStorage ?? _web_sql_flags__WEBPACK_IMPORTED_MODULE_4__.TemporaryStorageOption.MEMORY};`;
362
363
  if (useWebWorker) {
363
364
  const optionsDbWorker = this.options.worker;
364
365
  const dbOpener = this.options.workerPort
@@ -370,12 +371,14 @@ class WASQLiteDBAdapter extends _powersync_common__WEBPACK_IMPORTED_MODULE_0__.B
370
371
  })))
371
372
  : (0,_worker_db_open_worker_database__WEBPACK_IMPORTED_MODULE_3__.getWorkerDatabaseOpener)(this.options.dbFilename, enableMultiTabs, optionsDbWorker);
372
373
  this.methods = await dbOpener(this.options.dbFilename);
374
+ await this.methods.execute(tempStoreQuery);
373
375
  this.methods.registerOnTableChange(comlink__WEBPACK_IMPORTED_MODULE_6__.proxy((event) => {
374
376
  this.iterateListeners((cb) => cb.tablesUpdated?.(event));
375
377
  }));
376
378
  return;
377
379
  }
378
380
  this.methods = await (0,_shared_open_db__WEBPACK_IMPORTED_MODULE_2__._openDB)(this.options.dbFilename, { useWebWorker: false });
381
+ await this.methods.execute(tempStoreQuery);
379
382
  this.methods.registerOnTableChange((event) => {
380
383
  this.iterateListeners((cb) => cb.tablesUpdated?.(event));
381
384
  });
@@ -536,9 +539,15 @@ class WASQLiteDBAdapter extends _powersync_common__WEBPACK_IMPORTED_MODULE_0__.B
536
539
  __webpack_require__.r(__webpack_exports__);
537
540
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
538
541
  /* harmony export */ DEFAULT_WEB_SQL_FLAGS: () => (/* binding */ DEFAULT_WEB_SQL_FLAGS),
542
+ /* harmony export */ TemporaryStorageOption: () => (/* binding */ TemporaryStorageOption),
539
543
  /* harmony export */ isServerSide: () => (/* binding */ isServerSide),
540
544
  /* harmony export */ resolveWebSQLFlags: () => (/* binding */ resolveWebSQLFlags)
541
545
  /* harmony export */ });
546
+ var TemporaryStorageOption;
547
+ (function (TemporaryStorageOption) {
548
+ TemporaryStorageOption["MEMORY"] = "memory";
549
+ TemporaryStorageOption["FILESYSTEM"] = "file";
550
+ })(TemporaryStorageOption || (TemporaryStorageOption = {}));
542
551
  function isServerSide() {
543
552
  return typeof window == 'undefined';
544
553
  }
@@ -779,8 +788,8 @@ __webpack_require__.r(__webpack_exports__);
779
788
  /* harmony export */ _openDB: () => (/* binding */ _openDB)
780
789
  /* harmony export */ });
781
790
  /* harmony import */ var _journeyapps_wa_sqlite__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @journeyapps/wa-sqlite */ "../../node_modules/@journeyapps/wa-sqlite/src/sqlite-api.js");
782
- /* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! comlink */ "../../node_modules/comlink/dist/esm/comlink.mjs");
783
791
  /* harmony import */ var async_mutex__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! async-mutex */ "../../node_modules/async-mutex/index.mjs");
792
+ /* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! comlink */ "../../node_modules/comlink/dist/esm/comlink.mjs");
784
793
 
785
794
 
786
795
 
@@ -790,8 +799,13 @@ async function _openDB(dbFileName, options = { useWebWorker: true }) {
790
799
  const { default: moduleFactory } = await __webpack_require__.e(/*! import() */ "node_modules_journeyapps_wa-sqlite_dist_wa-sqlite-async_mjs").then(__webpack_require__.bind(__webpack_require__, /*! @journeyapps/wa-sqlite/dist/wa-sqlite-async.mjs */ "../../node_modules/@journeyapps/wa-sqlite/dist/wa-sqlite-async.mjs"));
791
800
  const module = await moduleFactory();
792
801
  const sqlite3 = _journeyapps_wa_sqlite__WEBPACK_IMPORTED_MODULE_0__.Factory(module);
802
+ /**
803
+ * Register the PowerSync core SQLite extension
804
+ */
805
+ module.ccall('powersync_init_static', 'int', []);
793
806
  const { IDBBatchAtomicVFS } = await __webpack_require__.e(/*! import() */ "node_modules_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js").then(__webpack_require__.bind(__webpack_require__, /*! @journeyapps/wa-sqlite/src/examples/IDBBatchAtomicVFS.js */ "../../node_modules/@journeyapps/wa-sqlite/src/examples/IDBBatchAtomicVFS.js"));
794
- const vfs = new IDBBatchAtomicVFS(dbFileName);
807
+ // @ts-expect-error The types for this static method are missing upstream
808
+ const vfs = await IDBBatchAtomicVFS.create(dbFileName, module, { lockPolicy: 'exclusive' });
795
809
  sqlite3.vfs_register(vfs, true);
796
810
  const db = await sqlite3.open_v2(dbFileName);
797
811
  const statementMutex = new async_mutex__WEBPACK_IMPORTED_MODULE_1__.Mutex();
@@ -807,7 +821,10 @@ async function _openDB(dbFileName, options = { useWebWorker: true }) {
807
821
  updatedTables.clear();
808
822
  Array.from(listeners.values()).forEach((l) => l(event));
809
823
  }
810
- sqlite3.register_table_onchange_hook(db, (opType, tableName, rowId) => {
824
+ sqlite3.update_hook(db, (updateType, dbName, tableName) => {
825
+ if (!tableName) {
826
+ return;
827
+ }
811
828
  updatedTables.add(tableName);
812
829
  if (updateTimer == null) {
813
830
  updateTimer = setTimeout(fireUpdates, 0);
@@ -889,40 +906,36 @@ async function _openDB(dbFileName, options = { useWebWorker: true }) {
889
906
  const executeBatch = async (sql, bindings) => {
890
907
  return _acquireExecuteLock(async () => {
891
908
  let affectedRows = 0;
892
- const str = sqlite3.str_new(db, sql);
893
- const query = sqlite3.str_value(str);
894
909
  try {
895
910
  await executeSingleStatement('BEGIN TRANSACTION');
896
- //Prepare statement once
897
- const prepared = await sqlite3.prepare_v2(db, query);
898
- if (prepared === null) {
899
- return {
900
- rowsAffected: 0,
901
- rows: { _array: [], length: 0 }
902
- };
903
- }
904
911
  const wrappedBindings = bindings ? bindings : [];
905
- for (const binding of wrappedBindings) {
906
- // TODO not sure why this is needed currently, but booleans break
907
- for (let i = 0; i < binding.length; i++) {
908
- const b = binding[i];
909
- if (typeof b == 'boolean') {
910
- binding[i] = b ? 1 : 0;
911
- }
912
- }
913
- //Reset bindings
914
- sqlite3.reset(prepared.stmt);
915
- if (bindings) {
916
- sqlite3.bind_collection(prepared.stmt, binding);
912
+ for await (const stmt of sqlite3.statements(db, sql)) {
913
+ if (stmt === null) {
914
+ return {
915
+ rowsAffected: 0,
916
+ rows: { _array: [], length: 0 }
917
+ };
917
918
  }
918
- const result = await sqlite3.step(prepared.stmt);
919
- if (result === _journeyapps_wa_sqlite__WEBPACK_IMPORTED_MODULE_0__.SQLITE_DONE) {
920
- //The value returned by sqlite3_changes() immediately after an INSERT, UPDATE or DELETE statement run on a view is always zero.
921
- affectedRows += sqlite3.changes(db);
919
+ //Prepare statement once
920
+ for (const binding of wrappedBindings) {
921
+ // TODO not sure why this is needed currently, but booleans break
922
+ for (let i = 0; i < binding.length; i++) {
923
+ const b = binding[i];
924
+ if (typeof b == 'boolean') {
925
+ binding[i] = b ? 1 : 0;
926
+ }
927
+ }
928
+ if (bindings) {
929
+ sqlite3.bind_collection(stmt, binding);
930
+ }
931
+ const result = await sqlite3.step(stmt);
932
+ if (result === _journeyapps_wa_sqlite__WEBPACK_IMPORTED_MODULE_0__.SQLITE_DONE) {
933
+ //The value returned by sqlite3_changes() immediately after an INSERT, UPDATE or DELETE statement run on a view is always zero.
934
+ affectedRows += sqlite3.changes(db);
935
+ }
936
+ sqlite3.reset(stmt);
922
937
  }
923
938
  }
924
- //Finalize prepared statement
925
- await sqlite3.finalize(prepared.stmt);
926
939
  await executeSingleStatement('COMMIT');
927
940
  }
928
941
  catch (err) {
@@ -932,9 +945,6 @@ async function _openDB(dbFileName, options = { useWebWorker: true }) {
932
945
  rows: { _array: [], length: 0 }
933
946
  };
934
947
  }
935
- finally {
936
- sqlite3.str_finish(str);
937
- }
938
948
  const result = {
939
949
  rowsAffected: affectedRows,
940
950
  rows: { _array: [], length: 0 }
@@ -2283,6 +2293,9 @@ __webpack_require__.r(__webpack_exports__);
2283
2293
  /* harmony export */ SQLITE_OPEN_WAL: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_WAL),
2284
2294
  /* harmony export */ SQLITE_PERM: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_PERM),
2285
2295
  /* harmony export */ SQLITE_PRAGMA: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_PRAGMA),
2296
+ /* harmony export */ SQLITE_PREPARE_NORMALIZED: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_PREPARE_NORMALIZED),
2297
+ /* harmony export */ SQLITE_PREPARE_NO_VTAB: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_PREPARE_NO_VTAB),
2298
+ /* harmony export */ SQLITE_PREPARE_PERSISTENT: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_PREPARE_PERSISTENT),
2286
2299
  /* harmony export */ SQLITE_PROTOCOL: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_PROTOCOL),
2287
2300
  /* harmony export */ SQLITE_RANGE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_RANGE),
2288
2301
  /* harmony export */ SQLITE_READ: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_READ),
@@ -2329,6 +2342,8 @@ if (typeof BigInt.prototype['toJSON'] == 'undefined') {
2329
2342
  const MAX_INT64 = 0x7fffffffffffffffn;
2330
2343
  const MIN_INT64 = -0x8000000000000000n;
2331
2344
 
2345
+ const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
2346
+
2332
2347
  class SQLiteError extends Error {
2333
2348
  constructor(message, code) {
2334
2349
  super(message);
@@ -2338,10 +2353,6 @@ class SQLiteError extends Error {
2338
2353
 
2339
2354
  const async = true;
2340
2355
 
2341
- const onTableChangeCallbacks = {};
2342
- globalThis.__onTablesChanged = function(db, opType, tableName, rowId) {
2343
- onTableChangeCallbacks[db]?.(opType, tableName, rowId);
2344
- };
2345
2356
 
2346
2357
  /**
2347
2358
  * Builds a Javascript API from the Emscripten module. This API is still
@@ -2353,6 +2364,7 @@ globalThis.__onTablesChanged = function(db, opType, tableName, rowId) {
2353
2364
  function Factory(Module) {
2354
2365
  /** @type {SQLiteAPI} */ const sqlite3 = {};
2355
2366
 
2367
+ Module.retryOps = [];
2356
2368
  const sqliteFreeAddress = Module._getSqliteFree();
2357
2369
 
2358
2370
  // Allocate some space for 32-bit returned values.
@@ -2363,9 +2375,10 @@ function Factory(Module) {
2363
2375
  // memory (use sqlite3_free to deallocate).
2364
2376
  function createUTF8(s) {
2365
2377
  if (typeof s !== 'string') return 0;
2366
- const n = Module.lengthBytesUTF8(s);
2367
- const zts = Module._sqlite3_malloc(n + 1);
2368
- Module.stringToUTF8(s, zts, n + 1);
2378
+ const utf8 = new TextEncoder().encode(s);
2379
+ const zts = Module._sqlite3_malloc(utf8.byteLength + 1);
2380
+ Module.HEAPU8.set(utf8, zts);
2381
+ Module.HEAPU8[zts + utf8.byteLength] = 0;
2369
2382
  return zts;
2370
2383
  }
2371
2384
 
@@ -2475,7 +2488,6 @@ function Factory(Module) {
2475
2488
  const ptr = Module._sqlite3_malloc(byteLength);
2476
2489
  Module.HEAPU8.subarray(ptr).set(value);
2477
2490
  const result = f(stmt, i, ptr, byteLength, sqliteFreeAddress);
2478
- // trace(fname, result);
2479
2491
  return check(fname, result, mapStmtToDB.get(stmt));
2480
2492
  };
2481
2493
  })();
@@ -2486,7 +2498,6 @@ function Factory(Module) {
2486
2498
  return function(stmt) {
2487
2499
  verifyStatement(stmt);
2488
2500
  const result = f(stmt);
2489
- // trace(fname, result);
2490
2501
  return result;
2491
2502
  };
2492
2503
  })();
@@ -2497,7 +2508,6 @@ function Factory(Module) {
2497
2508
  return function(stmt, i, value) {
2498
2509
  verifyStatement(stmt);
2499
2510
  const result = f(stmt, i, value);
2500
- // trace(fname, result);
2501
2511
  return check(fname, result, mapStmtToDB.get(stmt));
2502
2512
  };
2503
2513
  })();
@@ -2510,7 +2520,6 @@ function Factory(Module) {
2510
2520
  if (value > 0x7fffffff || value < -0x80000000) return _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_RANGE;
2511
2521
 
2512
2522
  const result = f(stmt, i, value);
2513
- // trace(fname, result);
2514
2523
  return check(fname, result, mapStmtToDB.get(stmt));
2515
2524
  };
2516
2525
  })();
@@ -2525,7 +2534,6 @@ function Factory(Module) {
2525
2534
  const lo32 = value & 0xffffffffn;
2526
2535
  const hi32 = value >> 32n;
2527
2536
  const result = f(stmt, i, Number(lo32), Number(hi32));
2528
- // trace(fname, result);
2529
2537
  return check(fname, result, mapStmtToDB.get(stmt));
2530
2538
  };
2531
2539
  })();
@@ -2536,7 +2544,6 @@ function Factory(Module) {
2536
2544
  return function(stmt, i) {
2537
2545
  verifyStatement(stmt);
2538
2546
  const result = f(stmt, i);
2539
- // trace(fname, result);
2540
2547
  return check(fname, result, mapStmtToDB.get(stmt));
2541
2548
  };
2542
2549
  })();
@@ -2547,7 +2554,6 @@ function Factory(Module) {
2547
2554
  return function(stmt, i) {
2548
2555
  verifyStatement(stmt);
2549
2556
  const result = f(stmt, i);
2550
- // trace(fname, result);
2551
2557
  return result;
2552
2558
  };
2553
2559
  })();
@@ -2559,7 +2565,6 @@ function Factory(Module) {
2559
2565
  verifyStatement(stmt);
2560
2566
  const ptr = createUTF8(value);
2561
2567
  const result = f(stmt, i, ptr, -1, sqliteFreeAddress);
2562
- // trace(fname, result);
2563
2568
  return check(fname, result, mapStmtToDB.get(stmt));
2564
2569
  };
2565
2570
  })();
@@ -2570,11 +2575,20 @@ function Factory(Module) {
2570
2575
  return function(db) {
2571
2576
  verifyDatabase(db);
2572
2577
  const result = f(db);
2573
- // trace(fname, result);
2574
2578
  return result;
2575
2579
  };
2576
2580
  })();
2577
2581
 
2582
+ sqlite3.clear_bindings = (function() {
2583
+ const fname = 'sqlite3_clear_bindings';
2584
+ const f = Module.cwrap(fname, ...decl('n:n'));
2585
+ return function(stmt) {
2586
+ verifyStatement(stmt);
2587
+ const result = f(stmt);
2588
+ return check(fname, result, mapStmtToDB.get(stmt));
2589
+ };
2590
+ })();
2591
+
2578
2592
  sqlite3.last_insert_id = (function() {
2579
2593
  const fname = 'sqlite3_last_insert_rowid';
2580
2594
  const f = Module.cwrap(fname, ...decl('n:n'));
@@ -2585,7 +2599,7 @@ function Factory(Module) {
2585
2599
  return result;
2586
2600
  };
2587
2601
  })();
2588
-
2602
+
2589
2603
  sqlite3.close = (function() {
2590
2604
  const fname = 'sqlite3_close';
2591
2605
  const f = Module.cwrap(fname, ...decl('n:n'), { async });
@@ -2626,7 +2640,6 @@ function Factory(Module) {
2626
2640
  const nBytes = sqlite3.column_bytes(stmt, iCol);
2627
2641
  const address = f(stmt, iCol);
2628
2642
  const result = Module.HEAPU8.subarray(address, address + nBytes);
2629
- // trace(fname, result);
2630
2643
  return result;
2631
2644
  };
2632
2645
  })();
@@ -2637,7 +2650,6 @@ function Factory(Module) {
2637
2650
  return function(stmt, iCol) {
2638
2651
  verifyStatement(stmt);
2639
2652
  const result = f(stmt, iCol);
2640
- // trace(fname, result);
2641
2653
  return result;
2642
2654
  };
2643
2655
  })();
@@ -2648,7 +2660,6 @@ function Factory(Module) {
2648
2660
  return function(stmt) {
2649
2661
  verifyStatement(stmt);
2650
2662
  const result = f(stmt);
2651
- // trace(fname, result);
2652
2663
  return result;
2653
2664
  };
2654
2665
  })();
@@ -2659,7 +2670,6 @@ function Factory(Module) {
2659
2670
  return function(stmt, iCol) {
2660
2671
  verifyStatement(stmt);
2661
2672
  const result = f(stmt, iCol);
2662
- // trace(fname, result);
2663
2673
  return result;
2664
2674
  };
2665
2675
  })();
@@ -2672,7 +2682,6 @@ function Factory(Module) {
2672
2682
  return function(stmt, iCol) {
2673
2683
  verifyStatement(stmt);
2674
2684
  const result = f(stmt, iCol);
2675
- // trace(fname, result);
2676
2685
  return result;
2677
2686
  };
2678
2687
  })();
@@ -2685,7 +2694,6 @@ function Factory(Module) {
2685
2694
  const lo32 = f(stmt, iCol);
2686
2695
  const hi32 = Module.getTempRet0();
2687
2696
  const result = cvt32x2ToBigInt(lo32, hi32);
2688
- // trace(fname, result);
2689
2697
  return result;
2690
2698
  };
2691
2699
  })();
@@ -2696,7 +2704,6 @@ function Factory(Module) {
2696
2704
  return function(stmt, iCol) {
2697
2705
  verifyStatement(stmt);
2698
2706
  const result = f(stmt, iCol);
2699
- // trace(fname, result);
2700
2707
  return result;
2701
2708
  };
2702
2709
  })();
@@ -2716,7 +2723,6 @@ function Factory(Module) {
2716
2723
  return function(stmt, iCol) {
2717
2724
  verifyStatement(stmt);
2718
2725
  const result = f(stmt, iCol);
2719
- // trace(fname, result);
2720
2726
  return result;
2721
2727
  };
2722
2728
  })();
@@ -2727,30 +2733,30 @@ function Factory(Module) {
2727
2733
  return function(stmt, iCol) {
2728
2734
  verifyStatement(stmt);
2729
2735
  const result = f(stmt, iCol);
2730
- // trace(fname, result);
2731
2736
  return result;
2732
2737
  };
2733
2738
  })();
2734
2739
 
2735
2740
  sqlite3.create_function = function(db, zFunctionName, nArg, eTextRep, pApp, xFunc, xStep, xFinal) {
2736
2741
  verifyDatabase(db);
2737
- if (xFunc && !xStep && !xFinal) {
2738
- const result = Module.createFunction(db, zFunctionName, nArg, eTextRep, pApp, xFunc);
2739
- return check('sqlite3_create_function', result, db);
2740
- }
2741
-
2742
- if (!xFunc && xStep && xFinal) {
2743
- const result = Module.createAggregate(db, zFunctionName, nArg, eTextRep, pApp, xStep, xFinal);
2744
- return check('sqlite3_create_function', result, db);
2742
+
2743
+ // Convert SQLite callback arguments to JavaScript-friendly arguments.
2744
+ function adapt(f) {
2745
+ return f instanceof AsyncFunction ?
2746
+ (async (ctx, n, values) => f(ctx, Module.HEAP32.subarray(values / 4, values / 4 + n))) :
2747
+ ((ctx, n, values) => f(ctx, Module.HEAP32.subarray(values / 4, values / 4 + n)));
2745
2748
  }
2746
2749
 
2747
- throw new SQLiteError('invalid function combination', _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_MISUSE);
2748
- };
2749
-
2750
- sqlite3.create_module = function(db, zName, module, appData) {
2751
- verifyDatabase(db);
2752
- const result = Module.createModule(db, zName, module, appData);
2753
- return check('sqlite3_create_module', result, db);
2750
+ const result = Module.create_function(
2751
+ db,
2752
+ zFunctionName,
2753
+ nArg,
2754
+ eTextRep,
2755
+ pApp,
2756
+ xFunc && adapt(xFunc),
2757
+ xStep && adapt(xStep),
2758
+ xFinal);
2759
+ return check('sqlite3_create_function', result, db);
2754
2760
  };
2755
2761
 
2756
2762
  sqlite3.data_count = (function() {
@@ -2759,20 +2765,10 @@ function Factory(Module) {
2759
2765
  return function(stmt) {
2760
2766
  verifyStatement(stmt);
2761
2767
  const result = f(stmt);
2762
- // trace(fname, result);
2763
2768
  return result;
2764
2769
  };
2765
2770
  })();
2766
2771
 
2767
- sqlite3.declare_vtab = (function() {
2768
- const fname = 'sqlite3_declare_vtab';
2769
- const f = Module.cwrap(fname, ...decl('ns:n'));
2770
- return function(pVTab, zSQL) {
2771
- const result = f(pVTab, zSQL);
2772
- return check('sqlite3_declare_vtab', result);
2773
- }
2774
- })();
2775
-
2776
2772
  sqlite3.exec = async function(db, sql, callback) {
2777
2773
  for await (const stmt of sqlite3.statements(db, sql)) {
2778
2774
  let columns;
@@ -2791,13 +2787,8 @@ function Factory(Module) {
2791
2787
  const fname = 'sqlite3_finalize';
2792
2788
  const f = Module.cwrap(fname, ...decl('n:n'), { async });
2793
2789
  return async function(stmt) {
2794
- if (!mapStmtToDB.has(stmt)) {
2795
- return _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_MISUSE;
2796
- }
2797
2790
  const result = await f(stmt);
2798
-
2799
- const db = mapStmtToDB.get(stmt);
2800
- mapStmtToDB.delete(stmt);
2791
+ mapStmtToDB.delete(stmt)
2801
2792
 
2802
2793
  // Don't throw on error here. Typically the error has already been
2803
2794
  // thrown and finalize() is part of the cleanup.
@@ -2847,70 +2838,26 @@ function Factory(Module) {
2847
2838
  return async function(zFilename, flags, zVfs) {
2848
2839
  flags = flags || _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_CREATE | _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_READWRITE;
2849
2840
  zVfs = createUTF8(zVfs);
2850
- Module.ccall('setup_powersync', 'int', []);
2851
-
2852
- const result = await f(zFilename, tmpPtr[0], flags, zVfs);
2853
-
2854
- const db = Module.getValue(tmpPtr[0], '*');
2855
-
2856
- databases.add(db);
2857
- Module._sqlite3_free(zVfs);
2858
-
2859
- Module.ccall('RegisterExtensionFunctions', 'void', ['number'], [db]);
2860
- check(fname, result);
2861
- return db;
2862
- };
2863
- })();
2864
-
2865
- sqlite3.register_table_onchange_hook = function(db, callback) {
2866
- // Register hooks for this DB as a global hook
2867
- // It will call the global handler above
2868
- Module.ccall('register_table_update_hook', 'int', ['number'], [db]);
2869
-
2870
- onTableChangeCallbacks[db] = function(opType, tableNamePtr, rowId) {
2871
- // Need to get the string from the pointer
2872
- // const tableName = Module.UTF8ToString(Module.getValue(tableNamePtr, '*'));
2873
- const memory = new DataView(Module.HEAPU8.buffer);
2874
-
2875
- // Find the null terminator to determine the string length
2876
- let length = 0;
2877
- while (memory.getUint8(tableNamePtr + length) !== 0) {
2878
- length++;
2879
- }
2880
-
2881
- // Extract the string content
2882
- const stringBytes = new Uint8Array(Module.HEAPU8.buffer, tableNamePtr, length);
2883
- const tableName = new TextDecoder().decode(stringBytes);
2841
+ try {
2842
+ // Allow retry operations.
2843
+ const rc = await retry(() => f(zFilename, tmpPtr[0], flags, zVfs));
2884
2844
 
2885
- /**
2886
- * Call the callback inside a setTimeout to avoid blocking SQLite.
2887
- * We use a setTimeout only after fetching data from the heap to avoid
2888
- * accessing memory which has been freed.
2889
- */
2890
- setTimeout(() => callback(opType, tableName, rowId), 0)
2891
- };
2892
- };
2845
+ const db = Module.getValue(tmpPtr[0], '*');
2846
+ databases.add(db);
2893
2847
 
2894
- sqlite3.prepare_v2 = (function() {
2895
- const fname = 'sqlite3_prepare_v2';
2896
- const f = Module.cwrap(fname, ...decl('nnnnn:n'), { async });
2897
- return async function(db, sql) {
2898
- const result = await f(db, sql, -1, tmpPtr[0], tmpPtr[1]);
2899
- check(fname, result, db);
2900
-
2901
- const stmt = Module.getValue(tmpPtr[0], '*');
2902
- if (stmt) {
2903
- mapStmtToDB.set(stmt, db);
2904
- return { stmt, sql: Module.getValue(tmpPtr[1], '*') };
2848
+ Module.ccall('RegisterExtensionFunctions', 'number', ['number'], [db]);
2849
+ check(fname, rc);
2850
+ return db;
2851
+ } finally {
2852
+ Module._sqlite3_free(zVfs);
2905
2853
  }
2906
- return null;
2907
2854
  };
2908
2855
  })();
2909
2856
 
2910
2857
  sqlite3.progress_handler = function(db, nProgressOps, handler, userData) {
2911
2858
  verifyDatabase(db);
2912
- Module.progressHandler(db, nProgressOps, handler, userData);
2913
- };
2859
+ Module.progress_handler(db, nProgressOps, handler, userData);
2860
+ };;
2914
2861
 
2915
2862
  sqlite3.reset = (function() {
2916
2863
  const fname = 'sqlite3_reset';
@@ -3020,9 +2967,27 @@ function Factory(Module) {
3020
2967
  return row;
3021
2968
  };
3022
2969
 
3023
- sqlite3.set_authorizer = function(db, authFunction, userData) {
2970
+ sqlite3.set_authorizer = function(db, xAuth, pApp) {
3024
2971
  verifyDatabase(db);
3025
- const result = Module.setAuthorizer(db, authFunction, userData);
2972
+
2973
+ // Convert SQLite callback arguments to JavaScript-friendly arguments.
2974
+ function cvtArgs(_, iAction, p3, p4, p5, p6) {
2975
+ return [
2976
+ _,
2977
+ iAction,
2978
+ Module.UTF8ToString(p3),
2979
+ Module.UTF8ToString(p4),
2980
+ Module.UTF8ToString(p5),
2981
+ Module.UTF8ToString(p6)
2982
+ ];
2983
+ };
2984
+ function adapt(f) {
2985
+ return f instanceof AsyncFunction ?
2986
+ (async (_, iAction, p3, p4, p5, p6) => f(...cvtArgs(_, iAction, p3, p4, p5, p6))) :
2987
+ ((_, iAction, p3, p4, p5, p6) => f(...cvtArgs(_, iAction, p3, p4, p5, p6)));
2988
+ }
2989
+
2990
+ const result = Module.set_authorizer(db, adapt(xAuth), pApp);
3026
2991
  return check('sqlite3_set_authorizer', result, db);
3027
2992
  };
3028
2993
 
@@ -3032,27 +2997,80 @@ function Factory(Module) {
3032
2997
  return function(stmt) {
3033
2998
  verifyStatement(stmt);
3034
2999
  const result = f(stmt);
3035
- // trace(fname, result);
3036
3000
  return result;
3037
3001
  };
3038
3002
  })();
3039
3003
 
3040
- sqlite3.statements = function(db, sql) {
3004
+ sqlite3.statements = function(db, sql, options = {}) {
3005
+ const prepare = Module.cwrap(
3006
+ 'sqlite3_prepare_v3',
3007
+ 'number',
3008
+ ['number', 'number', 'number', 'number', 'number', 'number'],
3009
+ { async: true });
3010
+
3041
3011
  return (async function*() {
3042
- const str = sqlite3.str_new(db, sql);
3043
- let prepared = { stmt: null, sql: sqlite3.str_value(str) };
3012
+ const onFinally = [];
3044
3013
  try {
3045
- while ((prepared = await sqlite3.prepare_v2(db, prepared.sql))) {
3046
- // console.log(sqlite3.sql(prepared.stmt));
3047
- yield prepared.stmt;
3048
- sqlite3.finalize(prepared.stmt);
3049
- prepared.stmt = null;
3014
+ // Encode SQL string to UTF-8.
3015
+ const utf8 = new TextEncoder().encode(sql);
3016
+
3017
+ // Copy encoded string to WebAssembly memory. The SQLite docs say
3018
+ // zero-termination is a minor optimization so add room for that.
3019
+ // Also add space for the statement handle and SQL tail pointer.
3020
+ const allocSize = utf8.byteLength - (utf8.byteLength % 4) + 12;
3021
+ const pzHead = Module._sqlite3_malloc(allocSize);
3022
+ const pzEnd = pzHead + utf8.byteLength + 1;
3023
+ onFinally.push(() => Module._sqlite3_free(pzHead));
3024
+ Module.HEAPU8.set(utf8, pzHead);
3025
+ Module.HEAPU8[pzEnd - 1] = 0;
3026
+
3027
+ // Use extra space for the statement handle and SQL tail pointer.
3028
+ const pStmt = pzHead + allocSize - 8;
3029
+ const pzTail = pzHead + allocSize - 4;
3030
+
3031
+ // Ensure that statement handles are not leaked.
3032
+ let stmt;
3033
+ function maybeFinalize() {
3034
+ if (stmt && !options.unscoped) {
3035
+ sqlite3.finalize(stmt);
3036
+ }
3037
+ stmt = 0;
3050
3038
  }
3039
+ onFinally.push(maybeFinalize);
3040
+
3041
+ // Loop over statements.
3042
+ Module.setValue(pzTail, pzHead, '*');
3043
+ do {
3044
+ // Reclaim resources for the previous iteration.
3045
+ maybeFinalize();
3046
+
3047
+ // Call sqlite3_prepare_v3() for the next statement.
3048
+ // Allow retry operations.
3049
+ const zTail = Module.getValue(pzTail, '*');
3050
+ const rc = await retry(() => {
3051
+ return prepare(
3052
+ db,
3053
+ zTail,
3054
+ pzEnd - pzTail,
3055
+ options.flags || 0,
3056
+ pStmt,
3057
+ pzTail);
3058
+ });
3059
+
3060
+ if (rc !== _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK) {
3061
+ check('sqlite3_prepare_v3', rc, db);
3062
+ }
3063
+
3064
+ stmt = Module.getValue(pStmt, '*');
3065
+ if (stmt) {
3066
+ mapStmtToDB.set(stmt, db);
3067
+ yield stmt;
3068
+ }
3069
+ } while (stmt);
3051
3070
  } finally {
3052
- if (prepared?.stmt) {
3053
- sqlite3.finalize(prepared.stmt);
3071
+ while (onFinally.length) {
3072
+ onFinally.pop()();
3054
3073
  }
3055
- sqlite3.str_finish(str);
3056
3074
  }
3057
3075
  })();
3058
3076
  };
@@ -3062,68 +3080,39 @@ function Factory(Module) {
3062
3080
  const f = Module.cwrap(fname, ...decl('n:n'), { async });
3063
3081
  return async function(stmt) {
3064
3082
  verifyStatement(stmt);
3065
- const result = await f(stmt);
3066
- return check(fname, result, mapStmtToDB.get(stmt), [_sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_ROW, _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_DONE]);
3067
- };
3068
- })();
3069
3083
 
3070
- // Duplicate some of the SQLite dynamic string API but without
3071
- // calling SQLite (except for memory allocation). We need some way
3072
- // to transfer Javascript strings and might as well use an API
3073
- // that mimics the SQLite API.
3074
- let stringId = 0;
3075
- const strings = new Map();
3076
-
3077
- sqlite3.str_new = function(db, s = '') {
3078
- const sBytes = Module.lengthBytesUTF8(s);
3079
- const str = stringId++ & 0xffffffff;
3080
- const data = {
3081
- offset: Module._sqlite3_malloc(sBytes + 1),
3082
- bytes: sBytes
3084
+ // Allow retry operations.
3085
+ const rc = await retry(() => f(stmt));
3086
+
3087
+ return check(fname, rc, mapStmtToDB.get(stmt), [_sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_ROW, _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_DONE]);
3083
3088
  };
3084
- strings.set(str, data);
3085
- Module.stringToUTF8(s, data.offset, data.bytes + 1);
3086
- return str;
3087
- };
3089
+ })();
3088
3090
 
3089
- sqlite3.str_appendall = function(str, s) {
3090
- if (!strings.has(str)) {
3091
- throw new SQLiteError('not a string', _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_MISUSE);
3092
- }
3093
- const data = strings.get(str);
3094
-
3095
- const sBytes = Module.lengthBytesUTF8(s);
3096
- const newBytes = data.bytes + sBytes;
3097
- const newOffset = Module._sqlite3_malloc(newBytes + 1);
3098
- const newArray = Module.HEAPU8.subarray(newOffset, newOffset + newBytes + 1);
3099
- newArray.set(Module.HEAPU8.subarray(data.offset, data.offset + data.bytes));
3100
- Module.stringToUTF8(s, newOffset + data.bytes, sBytes + 1);
3101
-
3102
- Module._sqlite3_free(data.offset);
3103
- data.offset = newOffset;
3104
- data.bytes = newBytes;
3105
- strings.set(str, data);
3091
+ sqlite3.commit_hook = function(db, xCommitHook) {
3092
+ verifyDatabase(db);
3093
+ Module.commit_hook(db, xCommitHook);
3106
3094
  };
3107
3095
 
3108
- sqlite3.str_finish = function(str) {
3109
- if (!strings.has(str)) {
3110
- throw new SQLiteError('not a string', _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_MISUSE);
3111
- }
3112
- const data = strings.get(str);
3113
- strings.delete(str);
3114
- Module._sqlite3_free(data.offset);
3115
- };
3096
+ sqlite3.update_hook = function(db, xUpdateHook) {
3097
+ verifyDatabase(db);
3116
3098
 
3117
- sqlite3.str_value = function(str) {
3118
- if (!strings.has(str)) {
3119
- throw new SQLiteError('not a string', _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_MISUSE);
3099
+ // Convert SQLite callback arguments to JavaScript-friendly arguments.
3100
+ function cvtArgs(iUpdateType, dbName, tblName, lo32, hi32) {
3101
+ return [
3102
+ iUpdateType,
3103
+ Module.UTF8ToString(dbName),
3104
+ Module.UTF8ToString(tblName),
3105
+ cvt32x2ToBigInt(lo32, hi32)
3106
+ ];
3107
+ };
3108
+ function adapt(f) {
3109
+ return f instanceof AsyncFunction ?
3110
+ (async (iUpdateType, dbName, tblName, lo32, hi32) => f(...cvtArgs(iUpdateType, dbName, tblName, lo32, hi32))) :
3111
+ ((iUpdateType, dbName, tblName, lo32, hi32) => f(...cvtArgs(iUpdateType, dbName, tblName, lo32, hi32)));
3120
3112
  }
3121
- return strings.get(str).offset;
3122
- };
3123
3113
 
3124
- sqlite3.user_data = function(context) {
3125
- return Module.getFunctionUserData(context);
3126
- };
3114
+ Module.update_hook(db, adapt(xUpdateHook));
3115
+ };;
3127
3116
 
3128
3117
  sqlite3.value = function(pValue) {
3129
3118
  const type = sqlite3.value_type(pValue);
@@ -3152,7 +3141,6 @@ function Factory(Module) {
3152
3141
  const nBytes = sqlite3.value_bytes(pValue);
3153
3142
  const address = f(pValue);
3154
3143
  const result = Module.HEAPU8.subarray(address, address + nBytes);
3155
- // trace(fname, result);
3156
3144
  return result;
3157
3145
  };
3158
3146
  })();
@@ -3162,7 +3150,6 @@ function Factory(Module) {
3162
3150
  const f = Module.cwrap(fname, ...decl('n:n'));
3163
3151
  return function(pValue) {
3164
3152
  const result = f(pValue);
3165
- // trace(fname, result);
3166
3153
  return result;
3167
3154
  };
3168
3155
  })();
@@ -3172,7 +3159,6 @@ function Factory(Module) {
3172
3159
  const f = Module.cwrap(fname, ...decl('n:n'));
3173
3160
  return function(pValue) {
3174
3161
  const result = f(pValue);
3175
- // trace(fname, result);
3176
3162
  return result;
3177
3163
  };
3178
3164
  })();
@@ -3182,7 +3168,6 @@ function Factory(Module) {
3182
3168
  const f = Module.cwrap(fname, ...decl('n:n'));
3183
3169
  return function(pValue) {
3184
3170
  const result = f(pValue);
3185
- // trace(fname, result);
3186
3171
  return result;
3187
3172
  };
3188
3173
  })();
@@ -3194,7 +3179,6 @@ function Factory(Module) {
3194
3179
  const lo32 = f(pValue);
3195
3180
  const hi32 = Module.getTempRet0();
3196
3181
  const result = cvt32x2ToBigInt(lo32, hi32);
3197
- // trace(fname, result);
3198
3182
  return result;
3199
3183
  };
3200
3184
  })();
@@ -3204,7 +3188,6 @@ function Factory(Module) {
3204
3188
  const f = Module.cwrap(fname, ...decl('n:s'));
3205
3189
  return function(pValue) {
3206
3190
  const result = f(pValue);
3207
- // trace(fname, result);
3208
3191
  return result;
3209
3192
  };
3210
3193
  })();
@@ -3214,33 +3197,42 @@ function Factory(Module) {
3214
3197
  const f = Module.cwrap(fname, ...decl('n:n'));
3215
3198
  return function(pValue) {
3216
3199
  const result = f(pValue);
3217
- // trace(fname, result);
3218
3200
  return result;
3219
3201
  };
3220
3202
  })();
3221
3203
 
3222
3204
  sqlite3.vfs_register = function(vfs, makeDefault) {
3223
- const result = Module.registerVFS(vfs, makeDefault);
3205
+ const result = Module.vfs_register(vfs, makeDefault);
3224
3206
  return check('sqlite3_vfs_register', result);
3225
3207
  };
3226
3208
 
3227
3209
  function check(fname, result, db = null, allowed = [_sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK]) {
3228
- // trace(fname, result);
3229
3210
  if (allowed.includes(result)) return result;
3230
3211
  const message = db ? Module.ccall('sqlite3_errmsg', 'string', ['number'], [db]) : fname;
3231
3212
  throw new SQLiteError(message, result);
3232
3213
  }
3233
3214
 
3234
- return sqlite3;
3235
- }
3215
+ // This function is used to automatically retry failed calls that
3216
+ // have pending retry operations that should allow the retry to
3217
+ // succeed.
3218
+ async function retry(f) {
3219
+ let rc;
3220
+ do {
3221
+ // Wait for all pending retry operations to complete. This is
3222
+ // normally empty on the first loop iteration.
3223
+ if (Module.retryOps.length) {
3224
+ await Promise.all(Module.retryOps);
3225
+ Module.retryOps = [];
3226
+ }
3227
+
3228
+ rc = await f();
3229
+
3230
+ // Retry on failure with new pending retry operations.
3231
+ } while (rc && Module.retryOps.length);
3232
+ return rc;
3233
+ }
3236
3234
 
3237
- function trace(...args) {
3238
- // const date = new Date();
3239
- // const t = date.getHours().toString().padStart(2, '0') + ':' +
3240
- // date.getMinutes().toString().padStart(2, '0') + ':' +
3241
- // date.getSeconds().toString().padStart(2, '0') + '.' +
3242
- // date.getMilliseconds().toString().padStart(3, '0');
3243
- // console.debug(t, ...args);
3235
+ return sqlite3;
3244
3236
  }
3245
3237
 
3246
3238
  // Helper function to use a more compact signature specification.
@@ -3490,6 +3482,9 @@ __webpack_require__.r(__webpack_exports__);
3490
3482
  /* harmony export */ SQLITE_OPEN_WAL: () => (/* binding */ SQLITE_OPEN_WAL),
3491
3483
  /* harmony export */ SQLITE_PERM: () => (/* binding */ SQLITE_PERM),
3492
3484
  /* harmony export */ SQLITE_PRAGMA: () => (/* binding */ SQLITE_PRAGMA),
3485
+ /* harmony export */ SQLITE_PREPARE_NORMALIZED: () => (/* binding */ SQLITE_PREPARE_NORMALIZED),
3486
+ /* harmony export */ SQLITE_PREPARE_NO_VTAB: () => (/* binding */ SQLITE_PREPARE_NO_VTAB),
3487
+ /* harmony export */ SQLITE_PREPARE_PERSISTENT: () => (/* binding */ SQLITE_PREPARE_PERSISTENT),
3493
3488
  /* harmony export */ SQLITE_PROTOCOL: () => (/* binding */ SQLITE_PROTOCOL),
3494
3489
  /* harmony export */ SQLITE_RANGE: () => (/* binding */ SQLITE_RANGE),
3495
3490
  /* harmony export */ SQLITE_READ: () => (/* binding */ SQLITE_READ),
@@ -3788,6 +3783,10 @@ const SQLITE_LIMIT_VARIABLE_NUMBER = 9;
3788
3783
  const SQLITE_LIMIT_TRIGGER_DEPTH = 10;
3789
3784
  const SQLITE_LIMIT_WORKER_THREADS = 11;
3790
3785
 
3786
+ const SQLITE_PREPARE_PERSISTENT = 0x01;
3787
+ const SQLITE_PREPARE_NORMALIZED = 0x02;
3788
+ const SQLITE_PREPARE_NO_VTAB = 0x04;
3789
+
3791
3790
  /***/ }),
3792
3791
 
3793
3792
  /***/ "../common/dist/bundle.mjs":