@powersync/web 1.10.2 → 1.11.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 (20) hide show
  1. package/dist/24cd027f23123a1360de.wasm +0 -0
  2. package/dist/_journeyapps_wa-sqlite-_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js-async-mutex-c-3cff7d0.index.umd.js +325 -0
  3. package/dist/_journeyapps_wa-sqlite-_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js-async-mutex-c-3cff7d0.index.umd.js.map +1 -0
  4. package/dist/_journeyapps_wa-sqlite-_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js-async-mutex-c-3cff7d1.index.umd.js +325 -0
  5. package/dist/_journeyapps_wa-sqlite-_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js-async-mutex-c-3cff7d1.index.umd.js.map +1 -0
  6. package/dist/index.umd.js +48 -177
  7. package/dist/index.umd.js.map +1 -1
  8. package/dist/worker/SharedSyncImplementation.umd.js +223 -233
  9. package/dist/worker/SharedSyncImplementation.umd.js.map +1 -1
  10. package/dist/worker/WASQLiteDB.umd.js +223 -233
  11. package/dist/worker/WASQLiteDB.umd.js.map +1 -1
  12. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite-async_mjs.umd.js +2 -132
  13. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite-async_mjs.umd.js.map +1 -1
  14. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js.umd.js +1707 -1372
  15. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js.umd.js.map +1 -1
  16. package/lib/package.json +3 -3
  17. package/lib/src/shared/open-db.js +36 -35
  18. package/lib/tsconfig.tsbuildinfo +1 -1
  19. package/package.json +3 -3
  20. package/dist/5fe5ed837a91c836c24f.wasm +0 -0
@@ -34,8 +34,8 @@ __webpack_require__.r(__webpack_exports__);
34
34
  /* harmony export */ _openDB: () => (/* binding */ _openDB)
35
35
  /* harmony export */ });
36
36
  /* harmony import */ var _journeyapps_wa_sqlite__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @journeyapps/wa-sqlite */ "../../node_modules/@journeyapps/wa-sqlite/src/sqlite-api.js");
37
- /* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! comlink */ "../../node_modules/comlink/dist/esm/comlink.mjs");
38
37
  /* harmony import */ var async_mutex__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! async-mutex */ "../../node_modules/async-mutex/index.mjs");
38
+ /* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! comlink */ "../../node_modules/comlink/dist/esm/comlink.mjs");
39
39
 
40
40
 
41
41
 
@@ -45,8 +45,13 @@ async function _openDB(dbFileName, options = { useWebWorker: true }) {
45
45
  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"));
46
46
  const module = await moduleFactory();
47
47
  const sqlite3 = _journeyapps_wa_sqlite__WEBPACK_IMPORTED_MODULE_0__.Factory(module);
48
+ /**
49
+ * Register the PowerSync core SQLite extension
50
+ */
51
+ module.ccall('powersync_init_static', 'int', []);
48
52
  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"));
49
- const vfs = new IDBBatchAtomicVFS(dbFileName);
53
+ // @ts-expect-error The types for this static method are missing upstream
54
+ const vfs = await IDBBatchAtomicVFS.create(dbFileName, module, { lockPolicy: 'exclusive' });
50
55
  sqlite3.vfs_register(vfs, true);
51
56
  const db = await sqlite3.open_v2(dbFileName);
52
57
  const statementMutex = new async_mutex__WEBPACK_IMPORTED_MODULE_1__.Mutex();
@@ -62,7 +67,10 @@ async function _openDB(dbFileName, options = { useWebWorker: true }) {
62
67
  updatedTables.clear();
63
68
  Array.from(listeners.values()).forEach((l) => l(event));
64
69
  }
65
- sqlite3.register_table_onchange_hook(db, (opType, tableName, rowId) => {
70
+ sqlite3.update_hook(db, (updateType, dbName, tableName) => {
71
+ if (!tableName) {
72
+ return;
73
+ }
66
74
  updatedTables.add(tableName);
67
75
  if (updateTimer == null) {
68
76
  updateTimer = setTimeout(fireUpdates, 0);
@@ -144,40 +152,36 @@ async function _openDB(dbFileName, options = { useWebWorker: true }) {
144
152
  const executeBatch = async (sql, bindings) => {
145
153
  return _acquireExecuteLock(async () => {
146
154
  let affectedRows = 0;
147
- const str = sqlite3.str_new(db, sql);
148
- const query = sqlite3.str_value(str);
149
155
  try {
150
156
  await executeSingleStatement('BEGIN TRANSACTION');
151
- //Prepare statement once
152
- const prepared = await sqlite3.prepare_v2(db, query);
153
- if (prepared === null) {
154
- return {
155
- rowsAffected: 0,
156
- rows: { _array: [], length: 0 }
157
- };
158
- }
159
157
  const wrappedBindings = bindings ? bindings : [];
160
- for (const binding of wrappedBindings) {
161
- // TODO not sure why this is needed currently, but booleans break
162
- for (let i = 0; i < binding.length; i++) {
163
- const b = binding[i];
164
- if (typeof b == 'boolean') {
165
- binding[i] = b ? 1 : 0;
166
- }
167
- }
168
- //Reset bindings
169
- sqlite3.reset(prepared.stmt);
170
- if (bindings) {
171
- sqlite3.bind_collection(prepared.stmt, binding);
158
+ for await (const stmt of sqlite3.statements(db, sql)) {
159
+ if (stmt === null) {
160
+ return {
161
+ rowsAffected: 0,
162
+ rows: { _array: [], length: 0 }
163
+ };
172
164
  }
173
- const result = await sqlite3.step(prepared.stmt);
174
- if (result === _journeyapps_wa_sqlite__WEBPACK_IMPORTED_MODULE_0__.SQLITE_DONE) {
175
- //The value returned by sqlite3_changes() immediately after an INSERT, UPDATE or DELETE statement run on a view is always zero.
176
- affectedRows += sqlite3.changes(db);
165
+ //Prepare statement once
166
+ for (const binding of wrappedBindings) {
167
+ // TODO not sure why this is needed currently, but booleans break
168
+ for (let i = 0; i < binding.length; i++) {
169
+ const b = binding[i];
170
+ if (typeof b == 'boolean') {
171
+ binding[i] = b ? 1 : 0;
172
+ }
173
+ }
174
+ if (bindings) {
175
+ sqlite3.bind_collection(stmt, binding);
176
+ }
177
+ const result = await sqlite3.step(stmt);
178
+ if (result === _journeyapps_wa_sqlite__WEBPACK_IMPORTED_MODULE_0__.SQLITE_DONE) {
179
+ //The value returned by sqlite3_changes() immediately after an INSERT, UPDATE or DELETE statement run on a view is always zero.
180
+ affectedRows += sqlite3.changes(db);
181
+ }
182
+ sqlite3.reset(stmt);
177
183
  }
178
184
  }
179
- //Finalize prepared statement
180
- await sqlite3.finalize(prepared.stmt);
181
185
  await executeSingleStatement('COMMIT');
182
186
  }
183
187
  catch (err) {
@@ -187,9 +191,6 @@ async function _openDB(dbFileName, options = { useWebWorker: true }) {
187
191
  rows: { _array: [], length: 0 }
188
192
  };
189
193
  }
190
- finally {
191
- sqlite3.str_finish(str);
192
- }
193
194
  const result = {
194
195
  rowsAffected: affectedRows,
195
196
  rows: { _array: [], length: 0 }
@@ -1065,6 +1066,9 @@ __webpack_require__.r(__webpack_exports__);
1065
1066
  /* harmony export */ SQLITE_OPEN_WAL: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_WAL),
1066
1067
  /* harmony export */ SQLITE_PERM: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_PERM),
1067
1068
  /* harmony export */ SQLITE_PRAGMA: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_PRAGMA),
1069
+ /* harmony export */ SQLITE_PREPARE_NORMALIZED: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_PREPARE_NORMALIZED),
1070
+ /* harmony export */ SQLITE_PREPARE_NO_VTAB: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_PREPARE_NO_VTAB),
1071
+ /* harmony export */ SQLITE_PREPARE_PERSISTENT: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_PREPARE_PERSISTENT),
1068
1072
  /* harmony export */ SQLITE_PROTOCOL: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_PROTOCOL),
1069
1073
  /* harmony export */ SQLITE_RANGE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_RANGE),
1070
1074
  /* harmony export */ SQLITE_READ: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_READ),
@@ -1111,6 +1115,8 @@ if (typeof BigInt.prototype['toJSON'] == 'undefined') {
1111
1115
  const MAX_INT64 = 0x7fffffffffffffffn;
1112
1116
  const MIN_INT64 = -0x8000000000000000n;
1113
1117
 
1118
+ const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
1119
+
1114
1120
  class SQLiteError extends Error {
1115
1121
  constructor(message, code) {
1116
1122
  super(message);
@@ -1120,10 +1126,6 @@ class SQLiteError extends Error {
1120
1126
 
1121
1127
  const async = true;
1122
1128
 
1123
- const onTableChangeCallbacks = {};
1124
- globalThis.__onTablesChanged = function(db, opType, tableName, rowId) {
1125
- onTableChangeCallbacks[db]?.(opType, tableName, rowId);
1126
- };
1127
1129
 
1128
1130
  /**
1129
1131
  * Builds a Javascript API from the Emscripten module. This API is still
@@ -1135,6 +1137,7 @@ globalThis.__onTablesChanged = function(db, opType, tableName, rowId) {
1135
1137
  function Factory(Module) {
1136
1138
  /** @type {SQLiteAPI} */ const sqlite3 = {};
1137
1139
 
1140
+ Module.retryOps = [];
1138
1141
  const sqliteFreeAddress = Module._getSqliteFree();
1139
1142
 
1140
1143
  // Allocate some space for 32-bit returned values.
@@ -1145,9 +1148,10 @@ function Factory(Module) {
1145
1148
  // memory (use sqlite3_free to deallocate).
1146
1149
  function createUTF8(s) {
1147
1150
  if (typeof s !== 'string') return 0;
1148
- const n = Module.lengthBytesUTF8(s);
1149
- const zts = Module._sqlite3_malloc(n + 1);
1150
- Module.stringToUTF8(s, zts, n + 1);
1151
+ const utf8 = new TextEncoder().encode(s);
1152
+ const zts = Module._sqlite3_malloc(utf8.byteLength + 1);
1153
+ Module.HEAPU8.set(utf8, zts);
1154
+ Module.HEAPU8[zts + utf8.byteLength] = 0;
1151
1155
  return zts;
1152
1156
  }
1153
1157
 
@@ -1257,7 +1261,6 @@ function Factory(Module) {
1257
1261
  const ptr = Module._sqlite3_malloc(byteLength);
1258
1262
  Module.HEAPU8.subarray(ptr).set(value);
1259
1263
  const result = f(stmt, i, ptr, byteLength, sqliteFreeAddress);
1260
- // trace(fname, result);
1261
1264
  return check(fname, result, mapStmtToDB.get(stmt));
1262
1265
  };
1263
1266
  })();
@@ -1268,7 +1271,6 @@ function Factory(Module) {
1268
1271
  return function(stmt) {
1269
1272
  verifyStatement(stmt);
1270
1273
  const result = f(stmt);
1271
- // trace(fname, result);
1272
1274
  return result;
1273
1275
  };
1274
1276
  })();
@@ -1279,7 +1281,6 @@ function Factory(Module) {
1279
1281
  return function(stmt, i, value) {
1280
1282
  verifyStatement(stmt);
1281
1283
  const result = f(stmt, i, value);
1282
- // trace(fname, result);
1283
1284
  return check(fname, result, mapStmtToDB.get(stmt));
1284
1285
  };
1285
1286
  })();
@@ -1292,7 +1293,6 @@ function Factory(Module) {
1292
1293
  if (value > 0x7fffffff || value < -0x80000000) return _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_RANGE;
1293
1294
 
1294
1295
  const result = f(stmt, i, value);
1295
- // trace(fname, result);
1296
1296
  return check(fname, result, mapStmtToDB.get(stmt));
1297
1297
  };
1298
1298
  })();
@@ -1307,7 +1307,6 @@ function Factory(Module) {
1307
1307
  const lo32 = value & 0xffffffffn;
1308
1308
  const hi32 = value >> 32n;
1309
1309
  const result = f(stmt, i, Number(lo32), Number(hi32));
1310
- // trace(fname, result);
1311
1310
  return check(fname, result, mapStmtToDB.get(stmt));
1312
1311
  };
1313
1312
  })();
@@ -1318,7 +1317,6 @@ function Factory(Module) {
1318
1317
  return function(stmt, i) {
1319
1318
  verifyStatement(stmt);
1320
1319
  const result = f(stmt, i);
1321
- // trace(fname, result);
1322
1320
  return check(fname, result, mapStmtToDB.get(stmt));
1323
1321
  };
1324
1322
  })();
@@ -1329,7 +1327,6 @@ function Factory(Module) {
1329
1327
  return function(stmt, i) {
1330
1328
  verifyStatement(stmt);
1331
1329
  const result = f(stmt, i);
1332
- // trace(fname, result);
1333
1330
  return result;
1334
1331
  };
1335
1332
  })();
@@ -1341,7 +1338,6 @@ function Factory(Module) {
1341
1338
  verifyStatement(stmt);
1342
1339
  const ptr = createUTF8(value);
1343
1340
  const result = f(stmt, i, ptr, -1, sqliteFreeAddress);
1344
- // trace(fname, result);
1345
1341
  return check(fname, result, mapStmtToDB.get(stmt));
1346
1342
  };
1347
1343
  })();
@@ -1352,11 +1348,20 @@ function Factory(Module) {
1352
1348
  return function(db) {
1353
1349
  verifyDatabase(db);
1354
1350
  const result = f(db);
1355
- // trace(fname, result);
1356
1351
  return result;
1357
1352
  };
1358
1353
  })();
1359
1354
 
1355
+ sqlite3.clear_bindings = (function() {
1356
+ const fname = 'sqlite3_clear_bindings';
1357
+ const f = Module.cwrap(fname, ...decl('n:n'));
1358
+ return function(stmt) {
1359
+ verifyStatement(stmt);
1360
+ const result = f(stmt);
1361
+ return check(fname, result, mapStmtToDB.get(stmt));
1362
+ };
1363
+ })();
1364
+
1360
1365
  sqlite3.last_insert_id = (function() {
1361
1366
  const fname = 'sqlite3_last_insert_rowid';
1362
1367
  const f = Module.cwrap(fname, ...decl('n:n'));
@@ -1367,7 +1372,7 @@ function Factory(Module) {
1367
1372
  return result;
1368
1373
  };
1369
1374
  })();
1370
-
1375
+
1371
1376
  sqlite3.close = (function() {
1372
1377
  const fname = 'sqlite3_close';
1373
1378
  const f = Module.cwrap(fname, ...decl('n:n'), { async });
@@ -1408,7 +1413,6 @@ function Factory(Module) {
1408
1413
  const nBytes = sqlite3.column_bytes(stmt, iCol);
1409
1414
  const address = f(stmt, iCol);
1410
1415
  const result = Module.HEAPU8.subarray(address, address + nBytes);
1411
- // trace(fname, result);
1412
1416
  return result;
1413
1417
  };
1414
1418
  })();
@@ -1419,7 +1423,6 @@ function Factory(Module) {
1419
1423
  return function(stmt, iCol) {
1420
1424
  verifyStatement(stmt);
1421
1425
  const result = f(stmt, iCol);
1422
- // trace(fname, result);
1423
1426
  return result;
1424
1427
  };
1425
1428
  })();
@@ -1430,7 +1433,6 @@ function Factory(Module) {
1430
1433
  return function(stmt) {
1431
1434
  verifyStatement(stmt);
1432
1435
  const result = f(stmt);
1433
- // trace(fname, result);
1434
1436
  return result;
1435
1437
  };
1436
1438
  })();
@@ -1441,7 +1443,6 @@ function Factory(Module) {
1441
1443
  return function(stmt, iCol) {
1442
1444
  verifyStatement(stmt);
1443
1445
  const result = f(stmt, iCol);
1444
- // trace(fname, result);
1445
1446
  return result;
1446
1447
  };
1447
1448
  })();
@@ -1454,7 +1455,6 @@ function Factory(Module) {
1454
1455
  return function(stmt, iCol) {
1455
1456
  verifyStatement(stmt);
1456
1457
  const result = f(stmt, iCol);
1457
- // trace(fname, result);
1458
1458
  return result;
1459
1459
  };
1460
1460
  })();
@@ -1467,7 +1467,6 @@ function Factory(Module) {
1467
1467
  const lo32 = f(stmt, iCol);
1468
1468
  const hi32 = Module.getTempRet0();
1469
1469
  const result = cvt32x2ToBigInt(lo32, hi32);
1470
- // trace(fname, result);
1471
1470
  return result;
1472
1471
  };
1473
1472
  })();
@@ -1478,7 +1477,6 @@ function Factory(Module) {
1478
1477
  return function(stmt, iCol) {
1479
1478
  verifyStatement(stmt);
1480
1479
  const result = f(stmt, iCol);
1481
- // trace(fname, result);
1482
1480
  return result;
1483
1481
  };
1484
1482
  })();
@@ -1498,7 +1496,6 @@ function Factory(Module) {
1498
1496
  return function(stmt, iCol) {
1499
1497
  verifyStatement(stmt);
1500
1498
  const result = f(stmt, iCol);
1501
- // trace(fname, result);
1502
1499
  return result;
1503
1500
  };
1504
1501
  })();
@@ -1509,30 +1506,30 @@ function Factory(Module) {
1509
1506
  return function(stmt, iCol) {
1510
1507
  verifyStatement(stmt);
1511
1508
  const result = f(stmt, iCol);
1512
- // trace(fname, result);
1513
1509
  return result;
1514
1510
  };
1515
1511
  })();
1516
1512
 
1517
1513
  sqlite3.create_function = function(db, zFunctionName, nArg, eTextRep, pApp, xFunc, xStep, xFinal) {
1518
1514
  verifyDatabase(db);
1519
- if (xFunc && !xStep && !xFinal) {
1520
- const result = Module.createFunction(db, zFunctionName, nArg, eTextRep, pApp, xFunc);
1521
- return check('sqlite3_create_function', result, db);
1515
+
1516
+ // Convert SQLite callback arguments to JavaScript-friendly arguments.
1517
+ function adapt(f) {
1518
+ return f instanceof AsyncFunction ?
1519
+ (async (ctx, n, values) => f(ctx, Module.HEAP32.subarray(values / 4, values / 4 + n))) :
1520
+ ((ctx, n, values) => f(ctx, Module.HEAP32.subarray(values / 4, values / 4 + n)));
1522
1521
  }
1523
1522
 
1524
- if (!xFunc && xStep && xFinal) {
1525
- const result = Module.createAggregate(db, zFunctionName, nArg, eTextRep, pApp, xStep, xFinal);
1526
- return check('sqlite3_create_function', result, db);
1527
- }
1528
-
1529
- throw new SQLiteError('invalid function combination', _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_MISUSE);
1530
- };
1531
-
1532
- sqlite3.create_module = function(db, zName, module, appData) {
1533
- verifyDatabase(db);
1534
- const result = Module.createModule(db, zName, module, appData);
1535
- return check('sqlite3_create_module', result, db);
1523
+ const result = Module.create_function(
1524
+ db,
1525
+ zFunctionName,
1526
+ nArg,
1527
+ eTextRep,
1528
+ pApp,
1529
+ xFunc && adapt(xFunc),
1530
+ xStep && adapt(xStep),
1531
+ xFinal);
1532
+ return check('sqlite3_create_function', result, db);
1536
1533
  };
1537
1534
 
1538
1535
  sqlite3.data_count = (function() {
@@ -1541,20 +1538,10 @@ function Factory(Module) {
1541
1538
  return function(stmt) {
1542
1539
  verifyStatement(stmt);
1543
1540
  const result = f(stmt);
1544
- // trace(fname, result);
1545
1541
  return result;
1546
1542
  };
1547
1543
  })();
1548
1544
 
1549
- sqlite3.declare_vtab = (function() {
1550
- const fname = 'sqlite3_declare_vtab';
1551
- const f = Module.cwrap(fname, ...decl('ns:n'));
1552
- return function(pVTab, zSQL) {
1553
- const result = f(pVTab, zSQL);
1554
- return check('sqlite3_declare_vtab', result);
1555
- }
1556
- })();
1557
-
1558
1545
  sqlite3.exec = async function(db, sql, callback) {
1559
1546
  for await (const stmt of sqlite3.statements(db, sql)) {
1560
1547
  let columns;
@@ -1573,13 +1560,8 @@ function Factory(Module) {
1573
1560
  const fname = 'sqlite3_finalize';
1574
1561
  const f = Module.cwrap(fname, ...decl('n:n'), { async });
1575
1562
  return async function(stmt) {
1576
- if (!mapStmtToDB.has(stmt)) {
1577
- return _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_MISUSE;
1578
- }
1579
1563
  const result = await f(stmt);
1580
-
1581
- const db = mapStmtToDB.get(stmt);
1582
- mapStmtToDB.delete(stmt);
1564
+ mapStmtToDB.delete(stmt)
1583
1565
 
1584
1566
  // Don't throw on error here. Typically the error has already been
1585
1567
  // thrown and finalize() is part of the cleanup.
@@ -1629,70 +1611,26 @@ function Factory(Module) {
1629
1611
  return async function(zFilename, flags, zVfs) {
1630
1612
  flags = flags || _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_CREATE | _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_READWRITE;
1631
1613
  zVfs = createUTF8(zVfs);
1632
- Module.ccall('setup_powersync', 'int', []);
1633
-
1634
- const result = await f(zFilename, tmpPtr[0], flags, zVfs);
1635
-
1636
- const db = Module.getValue(tmpPtr[0], '*');
1637
-
1638
- databases.add(db);
1639
- Module._sqlite3_free(zVfs);
1640
-
1641
- Module.ccall('RegisterExtensionFunctions', 'void', ['number'], [db]);
1642
- check(fname, result);
1643
- return db;
1644
- };
1645
- })();
1646
-
1647
- sqlite3.register_table_onchange_hook = function(db, callback) {
1648
- // Register hooks for this DB as a global hook
1649
- // It will call the global handler above
1650
- Module.ccall('register_table_update_hook', 'int', ['number'], [db]);
1651
-
1652
- onTableChangeCallbacks[db] = function(opType, tableNamePtr, rowId) {
1653
- // Need to get the string from the pointer
1654
- // const tableName = Module.UTF8ToString(Module.getValue(tableNamePtr, '*'));
1655
- const memory = new DataView(Module.HEAPU8.buffer);
1656
-
1657
- // Find the null terminator to determine the string length
1658
- let length = 0;
1659
- while (memory.getUint8(tableNamePtr + length) !== 0) {
1660
- length++;
1661
- }
1662
-
1663
- // Extract the string content
1664
- const stringBytes = new Uint8Array(Module.HEAPU8.buffer, tableNamePtr, length);
1665
- const tableName = new TextDecoder().decode(stringBytes);
1614
+ try {
1615
+ // Allow retry operations.
1616
+ const rc = await retry(() => f(zFilename, tmpPtr[0], flags, zVfs));
1666
1617
 
1667
- /**
1668
- * Call the callback inside a setTimeout to avoid blocking SQLite.
1669
- * We use a setTimeout only after fetching data from the heap to avoid
1670
- * accessing memory which has been freed.
1671
- */
1672
- setTimeout(() => callback(opType, tableName, rowId), 0)
1673
- };
1674
- };
1618
+ const db = Module.getValue(tmpPtr[0], '*');
1619
+ databases.add(db);
1675
1620
 
1676
- sqlite3.prepare_v2 = (function() {
1677
- const fname = 'sqlite3_prepare_v2';
1678
- const f = Module.cwrap(fname, ...decl('nnnnn:n'), { async });
1679
- return async function(db, sql) {
1680
- const result = await f(db, sql, -1, tmpPtr[0], tmpPtr[1]);
1681
- check(fname, result, db);
1682
-
1683
- const stmt = Module.getValue(tmpPtr[0], '*');
1684
- if (stmt) {
1685
- mapStmtToDB.set(stmt, db);
1686
- return { stmt, sql: Module.getValue(tmpPtr[1], '*') };
1621
+ Module.ccall('RegisterExtensionFunctions', 'number', ['number'], [db]);
1622
+ check(fname, rc);
1623
+ return db;
1624
+ } finally {
1625
+ Module._sqlite3_free(zVfs);
1687
1626
  }
1688
- return null;
1689
1627
  };
1690
1628
  })();
1691
1629
 
1692
1630
  sqlite3.progress_handler = function(db, nProgressOps, handler, userData) {
1693
1631
  verifyDatabase(db);
1694
- Module.progressHandler(db, nProgressOps, handler, userData);
1695
- };
1632
+ Module.progress_handler(db, nProgressOps, handler, userData);
1633
+ };;
1696
1634
 
1697
1635
  sqlite3.reset = (function() {
1698
1636
  const fname = 'sqlite3_reset';
@@ -1802,9 +1740,27 @@ function Factory(Module) {
1802
1740
  return row;
1803
1741
  };
1804
1742
 
1805
- sqlite3.set_authorizer = function(db, authFunction, userData) {
1743
+ sqlite3.set_authorizer = function(db, xAuth, pApp) {
1806
1744
  verifyDatabase(db);
1807
- const result = Module.setAuthorizer(db, authFunction, userData);
1745
+
1746
+ // Convert SQLite callback arguments to JavaScript-friendly arguments.
1747
+ function cvtArgs(_, iAction, p3, p4, p5, p6) {
1748
+ return [
1749
+ _,
1750
+ iAction,
1751
+ Module.UTF8ToString(p3),
1752
+ Module.UTF8ToString(p4),
1753
+ Module.UTF8ToString(p5),
1754
+ Module.UTF8ToString(p6)
1755
+ ];
1756
+ };
1757
+ function adapt(f) {
1758
+ return f instanceof AsyncFunction ?
1759
+ (async (_, iAction, p3, p4, p5, p6) => f(...cvtArgs(_, iAction, p3, p4, p5, p6))) :
1760
+ ((_, iAction, p3, p4, p5, p6) => f(...cvtArgs(_, iAction, p3, p4, p5, p6)));
1761
+ }
1762
+
1763
+ const result = Module.set_authorizer(db, adapt(xAuth), pApp);
1808
1764
  return check('sqlite3_set_authorizer', result, db);
1809
1765
  };
1810
1766
 
@@ -1814,27 +1770,80 @@ function Factory(Module) {
1814
1770
  return function(stmt) {
1815
1771
  verifyStatement(stmt);
1816
1772
  const result = f(stmt);
1817
- // trace(fname, result);
1818
1773
  return result;
1819
1774
  };
1820
1775
  })();
1821
1776
 
1822
- sqlite3.statements = function(db, sql) {
1777
+ sqlite3.statements = function(db, sql, options = {}) {
1778
+ const prepare = Module.cwrap(
1779
+ 'sqlite3_prepare_v3',
1780
+ 'number',
1781
+ ['number', 'number', 'number', 'number', 'number', 'number'],
1782
+ { async: true });
1783
+
1823
1784
  return (async function*() {
1824
- const str = sqlite3.str_new(db, sql);
1825
- let prepared = { stmt: null, sql: sqlite3.str_value(str) };
1785
+ const onFinally = [];
1826
1786
  try {
1827
- while ((prepared = await sqlite3.prepare_v2(db, prepared.sql))) {
1828
- // console.log(sqlite3.sql(prepared.stmt));
1829
- yield prepared.stmt;
1830
- sqlite3.finalize(prepared.stmt);
1831
- prepared.stmt = null;
1787
+ // Encode SQL string to UTF-8.
1788
+ const utf8 = new TextEncoder().encode(sql);
1789
+
1790
+ // Copy encoded string to WebAssembly memory. The SQLite docs say
1791
+ // zero-termination is a minor optimization so add room for that.
1792
+ // Also add space for the statement handle and SQL tail pointer.
1793
+ const allocSize = utf8.byteLength - (utf8.byteLength % 4) + 12;
1794
+ const pzHead = Module._sqlite3_malloc(allocSize);
1795
+ const pzEnd = pzHead + utf8.byteLength + 1;
1796
+ onFinally.push(() => Module._sqlite3_free(pzHead));
1797
+ Module.HEAPU8.set(utf8, pzHead);
1798
+ Module.HEAPU8[pzEnd - 1] = 0;
1799
+
1800
+ // Use extra space for the statement handle and SQL tail pointer.
1801
+ const pStmt = pzHead + allocSize - 8;
1802
+ const pzTail = pzHead + allocSize - 4;
1803
+
1804
+ // Ensure that statement handles are not leaked.
1805
+ let stmt;
1806
+ function maybeFinalize() {
1807
+ if (stmt && !options.unscoped) {
1808
+ sqlite3.finalize(stmt);
1809
+ }
1810
+ stmt = 0;
1832
1811
  }
1812
+ onFinally.push(maybeFinalize);
1813
+
1814
+ // Loop over statements.
1815
+ Module.setValue(pzTail, pzHead, '*');
1816
+ do {
1817
+ // Reclaim resources for the previous iteration.
1818
+ maybeFinalize();
1819
+
1820
+ // Call sqlite3_prepare_v3() for the next statement.
1821
+ // Allow retry operations.
1822
+ const zTail = Module.getValue(pzTail, '*');
1823
+ const rc = await retry(() => {
1824
+ return prepare(
1825
+ db,
1826
+ zTail,
1827
+ pzEnd - pzTail,
1828
+ options.flags || 0,
1829
+ pStmt,
1830
+ pzTail);
1831
+ });
1832
+
1833
+ if (rc !== _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK) {
1834
+ check('sqlite3_prepare_v3', rc, db);
1835
+ }
1836
+
1837
+ stmt = Module.getValue(pStmt, '*');
1838
+ if (stmt) {
1839
+ mapStmtToDB.set(stmt, db);
1840
+ yield stmt;
1841
+ }
1842
+ } while (stmt);
1833
1843
  } finally {
1834
- if (prepared?.stmt) {
1835
- sqlite3.finalize(prepared.stmt);
1844
+ while (onFinally.length) {
1845
+ onFinally.pop()();
1836
1846
  }
1837
- sqlite3.str_finish(str);
1838
1847
  }
1839
1848
  })();
1840
1849
  };
@@ -1844,68 +1853,39 @@ function Factory(Module) {
1844
1853
  const f = Module.cwrap(fname, ...decl('n:n'), { async });
1845
1854
  return async function(stmt) {
1846
1855
  verifyStatement(stmt);
1847
- const result = await f(stmt);
1848
- 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]);
1849
- };
1850
- })();
1851
1856
 
1852
- // Duplicate some of the SQLite dynamic string API but without
1853
- // calling SQLite (except for memory allocation). We need some way
1854
- // to transfer Javascript strings and might as well use an API
1855
- // that mimics the SQLite API.
1856
- let stringId = 0;
1857
- const strings = new Map();
1858
-
1859
- sqlite3.str_new = function(db, s = '') {
1860
- const sBytes = Module.lengthBytesUTF8(s);
1861
- const str = stringId++ & 0xffffffff;
1862
- const data = {
1863
- offset: Module._sqlite3_malloc(sBytes + 1),
1864
- bytes: sBytes
1857
+ // Allow retry operations.
1858
+ const rc = await retry(() => f(stmt));
1859
+
1860
+ 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]);
1865
1861
  };
1866
- strings.set(str, data);
1867
- Module.stringToUTF8(s, data.offset, data.bytes + 1);
1868
- return str;
1869
- };
1862
+ })();
1870
1863
 
1871
- sqlite3.str_appendall = function(str, s) {
1872
- if (!strings.has(str)) {
1873
- throw new SQLiteError('not a string', _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_MISUSE);
1874
- }
1875
- const data = strings.get(str);
1876
-
1877
- const sBytes = Module.lengthBytesUTF8(s);
1878
- const newBytes = data.bytes + sBytes;
1879
- const newOffset = Module._sqlite3_malloc(newBytes + 1);
1880
- const newArray = Module.HEAPU8.subarray(newOffset, newOffset + newBytes + 1);
1881
- newArray.set(Module.HEAPU8.subarray(data.offset, data.offset + data.bytes));
1882
- Module.stringToUTF8(s, newOffset + data.bytes, sBytes + 1);
1883
-
1884
- Module._sqlite3_free(data.offset);
1885
- data.offset = newOffset;
1886
- data.bytes = newBytes;
1887
- strings.set(str, data);
1864
+ sqlite3.commit_hook = function(db, xCommitHook) {
1865
+ verifyDatabase(db);
1866
+ Module.commit_hook(db, xCommitHook);
1888
1867
  };
1889
1868
 
1890
- sqlite3.str_finish = function(str) {
1891
- if (!strings.has(str)) {
1892
- throw new SQLiteError('not a string', _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_MISUSE);
1893
- }
1894
- const data = strings.get(str);
1895
- strings.delete(str);
1896
- Module._sqlite3_free(data.offset);
1897
- };
1869
+ sqlite3.update_hook = function(db, xUpdateHook) {
1870
+ verifyDatabase(db);
1898
1871
 
1899
- sqlite3.str_value = function(str) {
1900
- if (!strings.has(str)) {
1901
- throw new SQLiteError('not a string', _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_MISUSE);
1872
+ // Convert SQLite callback arguments to JavaScript-friendly arguments.
1873
+ function cvtArgs(iUpdateType, dbName, tblName, lo32, hi32) {
1874
+ return [
1875
+ iUpdateType,
1876
+ Module.UTF8ToString(dbName),
1877
+ Module.UTF8ToString(tblName),
1878
+ cvt32x2ToBigInt(lo32, hi32)
1879
+ ];
1880
+ };
1881
+ function adapt(f) {
1882
+ return f instanceof AsyncFunction ?
1883
+ (async (iUpdateType, dbName, tblName, lo32, hi32) => f(...cvtArgs(iUpdateType, dbName, tblName, lo32, hi32))) :
1884
+ ((iUpdateType, dbName, tblName, lo32, hi32) => f(...cvtArgs(iUpdateType, dbName, tblName, lo32, hi32)));
1902
1885
  }
1903
- return strings.get(str).offset;
1904
- };
1905
1886
 
1906
- sqlite3.user_data = function(context) {
1907
- return Module.getFunctionUserData(context);
1908
- };
1887
+ Module.update_hook(db, adapt(xUpdateHook));
1888
+ };;
1909
1889
 
1910
1890
  sqlite3.value = function(pValue) {
1911
1891
  const type = sqlite3.value_type(pValue);
@@ -1934,7 +1914,6 @@ function Factory(Module) {
1934
1914
  const nBytes = sqlite3.value_bytes(pValue);
1935
1915
  const address = f(pValue);
1936
1916
  const result = Module.HEAPU8.subarray(address, address + nBytes);
1937
- // trace(fname, result);
1938
1917
  return result;
1939
1918
  };
1940
1919
  })();
@@ -1944,7 +1923,6 @@ function Factory(Module) {
1944
1923
  const f = Module.cwrap(fname, ...decl('n:n'));
1945
1924
  return function(pValue) {
1946
1925
  const result = f(pValue);
1947
- // trace(fname, result);
1948
1926
  return result;
1949
1927
  };
1950
1928
  })();
@@ -1954,7 +1932,6 @@ function Factory(Module) {
1954
1932
  const f = Module.cwrap(fname, ...decl('n:n'));
1955
1933
  return function(pValue) {
1956
1934
  const result = f(pValue);
1957
- // trace(fname, result);
1958
1935
  return result;
1959
1936
  };
1960
1937
  })();
@@ -1964,7 +1941,6 @@ function Factory(Module) {
1964
1941
  const f = Module.cwrap(fname, ...decl('n:n'));
1965
1942
  return function(pValue) {
1966
1943
  const result = f(pValue);
1967
- // trace(fname, result);
1968
1944
  return result;
1969
1945
  };
1970
1946
  })();
@@ -1976,7 +1952,6 @@ function Factory(Module) {
1976
1952
  const lo32 = f(pValue);
1977
1953
  const hi32 = Module.getTempRet0();
1978
1954
  const result = cvt32x2ToBigInt(lo32, hi32);
1979
- // trace(fname, result);
1980
1955
  return result;
1981
1956
  };
1982
1957
  })();
@@ -1986,7 +1961,6 @@ function Factory(Module) {
1986
1961
  const f = Module.cwrap(fname, ...decl('n:s'));
1987
1962
  return function(pValue) {
1988
1963
  const result = f(pValue);
1989
- // trace(fname, result);
1990
1964
  return result;
1991
1965
  };
1992
1966
  })();
@@ -1996,33 +1970,42 @@ function Factory(Module) {
1996
1970
  const f = Module.cwrap(fname, ...decl('n:n'));
1997
1971
  return function(pValue) {
1998
1972
  const result = f(pValue);
1999
- // trace(fname, result);
2000
1973
  return result;
2001
1974
  };
2002
1975
  })();
2003
1976
 
2004
1977
  sqlite3.vfs_register = function(vfs, makeDefault) {
2005
- const result = Module.registerVFS(vfs, makeDefault);
1978
+ const result = Module.vfs_register(vfs, makeDefault);
2006
1979
  return check('sqlite3_vfs_register', result);
2007
1980
  };
2008
1981
 
2009
1982
  function check(fname, result, db = null, allowed = [_sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK]) {
2010
- // trace(fname, result);
2011
1983
  if (allowed.includes(result)) return result;
2012
1984
  const message = db ? Module.ccall('sqlite3_errmsg', 'string', ['number'], [db]) : fname;
2013
1985
  throw new SQLiteError(message, result);
2014
1986
  }
2015
1987
 
2016
- return sqlite3;
2017
- }
1988
+ // This function is used to automatically retry failed calls that
1989
+ // have pending retry operations that should allow the retry to
1990
+ // succeed.
1991
+ async function retry(f) {
1992
+ let rc;
1993
+ do {
1994
+ // Wait for all pending retry operations to complete. This is
1995
+ // normally empty on the first loop iteration.
1996
+ if (Module.retryOps.length) {
1997
+ await Promise.all(Module.retryOps);
1998
+ Module.retryOps = [];
1999
+ }
2000
+
2001
+ rc = await f();
2002
+
2003
+ // Retry on failure with new pending retry operations.
2004
+ } while (rc && Module.retryOps.length);
2005
+ return rc;
2006
+ }
2018
2007
 
2019
- function trace(...args) {
2020
- // const date = new Date();
2021
- // const t = date.getHours().toString().padStart(2, '0') + ':' +
2022
- // date.getMinutes().toString().padStart(2, '0') + ':' +
2023
- // date.getSeconds().toString().padStart(2, '0') + '.' +
2024
- // date.getMilliseconds().toString().padStart(3, '0');
2025
- // console.debug(t, ...args);
2008
+ return sqlite3;
2026
2009
  }
2027
2010
 
2028
2011
  // Helper function to use a more compact signature specification.
@@ -2271,6 +2254,9 @@ __webpack_require__.r(__webpack_exports__);
2271
2254
  /* harmony export */ SQLITE_OPEN_WAL: () => (/* binding */ SQLITE_OPEN_WAL),
2272
2255
  /* harmony export */ SQLITE_PERM: () => (/* binding */ SQLITE_PERM),
2273
2256
  /* harmony export */ SQLITE_PRAGMA: () => (/* binding */ SQLITE_PRAGMA),
2257
+ /* harmony export */ SQLITE_PREPARE_NORMALIZED: () => (/* binding */ SQLITE_PREPARE_NORMALIZED),
2258
+ /* harmony export */ SQLITE_PREPARE_NO_VTAB: () => (/* binding */ SQLITE_PREPARE_NO_VTAB),
2259
+ /* harmony export */ SQLITE_PREPARE_PERSISTENT: () => (/* binding */ SQLITE_PREPARE_PERSISTENT),
2274
2260
  /* harmony export */ SQLITE_PROTOCOL: () => (/* binding */ SQLITE_PROTOCOL),
2275
2261
  /* harmony export */ SQLITE_RANGE: () => (/* binding */ SQLITE_RANGE),
2276
2262
  /* harmony export */ SQLITE_READ: () => (/* binding */ SQLITE_READ),
@@ -2569,6 +2555,10 @@ const SQLITE_LIMIT_VARIABLE_NUMBER = 9;
2569
2555
  const SQLITE_LIMIT_TRIGGER_DEPTH = 10;
2570
2556
  const SQLITE_LIMIT_WORKER_THREADS = 11;
2571
2557
 
2558
+ const SQLITE_PREPARE_PERSISTENT = 0x01;
2559
+ const SQLITE_PREPARE_NORMALIZED = 0x02;
2560
+ const SQLITE_PREPARE_NO_VTAB = 0x04;
2561
+
2572
2562
  /***/ })
2573
2563
 
2574
2564
  /******/ });