Skip to content

Commit 24a090e

Browse files
Merge remote-tracking branch 'origin/master' into powersync_builds
2 parents e2ab7c3 + 59c792f commit 24a090e

File tree

3 files changed

+57
-1
lines changed

3 files changed

+57
-1
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
# @journeyapps/wa-sqlite
22

3+
## 0.4.1
4+
5+
### Patch Changes
6+
7+
- 588937a: Fix bug where table change update notifications would access invalid memory locations under certain conditions.
8+
9+
## 0.4.0
10+
11+
### Minor Changes
12+
13+
- 95b8ba1: powersync-sqlite-core 0.3.0
14+
315
## 0.3.0
416

517
### Minor Changes

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@journeyapps/wa-sqlite",
3-
"version": "0.3.0",
3+
"version": "0.4.1",
44
"publishConfig": {
55
"access": "public"
66
},

src/sqlite-api.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,50 @@ export function Factory(Module) {
532532
};
533533
})();
534534

535+
sqlite3.register_table_onchange_hook = function(db, callback) {
536+
// Register hooks for this DB as a global hook
537+
// It will call the global handler above
538+
Module.ccall('register_table_update_hook', 'int', ['number'], [db]);
539+
540+
onTableChangeCallbacks[db] = function(opType, tableNamePtr, rowId) {
541+
// Need to get the string from the pointer
542+
// const tableName = Module.UTF8ToString(Module.getValue(tableNamePtr, '*'));
543+
const memory = new DataView(Module.HEAPU8.buffer);
544+
545+
// Find the null terminator to determine the string length
546+
let length = 0;
547+
while (memory.getUint8(tableNamePtr + length) !== 0) {
548+
length++;
549+
}
550+
551+
// Extract the string content
552+
const stringBytes = new Uint8Array(Module.HEAPU8.buffer, tableNamePtr, length);
553+
const tableName = new TextDecoder().decode(stringBytes);
554+
555+
/**
556+
* Call the callback inside a setTimeout to avoid blocking SQLite.
557+
* We use a setTimeout only after fetching data from the heap to avoid
558+
* accessing memory which has been freed.
559+
*/
560+
setTimeout(() => callback(opType, tableName, rowId), 0)
561+
};
562+
};
563+
564+
sqlite3.prepare_v2 = (function() {
565+
const fname = 'sqlite3_prepare_v2';
566+
const f = Module.cwrap(fname, ...decl('nnnnn:n'), { async });
567+
return async function(db, sql) {
568+
const result = await f(db, sql, -1, tmpPtr[0], tmpPtr[1]);
569+
check(fname, result, db);
570+
571+
const stmt = Module.getValue(tmpPtr[0], '*');
572+
if (stmt) {
573+
mapStmtToDB.set(stmt, db);
574+
return { stmt, sql: Module.getValue(tmpPtr[1], '*') };
575+
}
576+
return null;
577+
};
578+
})();
535579

536580
sqlite3.progress_handler = function(db, nProgressOps, handler, userData) {
537581
verifyDatabase(db);

0 commit comments

Comments
 (0)