Skip to content

Commit 26c2c24

Browse files
fix: capacitor iOS Buffer read error (#933)
1 parent c730604 commit 26c2c24

3 files changed

Lines changed: 37 additions & 1 deletion

File tree

.changeset/rude-squids-unite.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@powersync/capacitor': patch
3+
---
4+
5+
Fixed "Error in reading buffer" error on iOS when connecting via WebSocket.

packages/capacitor/src/PowerSyncDatabase.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Capacitor } from '@capacitor/core';
22
import {
3+
BucketStorageAdapter,
34
DBAdapter,
45
MEMORY_TRIGGER_CLAIM_MANAGER,
56
PowerSyncBackendConnector,
@@ -11,8 +12,8 @@ import {
1112
WebRemote
1213
} from '@powersync/web';
1314
import { CapacitorSQLiteAdapter } from './adapter/CapacitorSQLiteAdapter.js';
15+
import { CapacitorBucketStorageAdapter } from './sync/CapacitorBucketStorageAdapter.js';
1416
import { CapacitorStreamingSyncImplementation } from './sync/CapacitorSyncImplementation.js';
15-
1617
/**
1718
* PowerSyncDatabase class for managing database connections and sync implementations.
1819
* This extends the WebPowerSyncDatabase to provide platform-specific implementations
@@ -69,6 +70,14 @@ export class PowerSyncDatabase extends WebPowerSyncDatabase {
6970
}
7071
}
7172

73+
protected generateBucketStorageAdapter(): BucketStorageAdapter {
74+
if (this.isNativeCapacitorPlatform) {
75+
return new CapacitorBucketStorageAdapter(this.database, this.logger);
76+
} else {
77+
return super.generateBucketStorageAdapter();
78+
}
79+
}
80+
7281
protected generateSyncStreamImplementation(
7382
connector: PowerSyncBackendConnector,
7483
options: RequiredAdditionalConnectionOptions
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { PowerSyncControlCommand, SqliteBucketStorage } from '@powersync/web';
2+
3+
export class CapacitorBucketStorageAdapter extends SqliteBucketStorage {
4+
control(op: PowerSyncControlCommand, payload: string | Uint8Array | ArrayBuffer | null): Promise<string> {
5+
if (payload instanceof Uint8Array && (payload as any)['_isBuffer'] == true) {
6+
/**
7+
* The Buffer polyfill, used in @powersync/common, is a Uint8Array subclass which defines additional fields like
8+
* `_isBuffer` and `parent` on its `prototype`. The additional fields are serialized when passed through the native bridge.
9+
* The Capacitor Community SQLite lib expects a dictionarty of indexes to numerical bytes.
10+
* The additiona fields (which are not an index to numerical byte mapping) cause the parsing logic in the SQLite lib to throw an error:
11+
* "Error in reading buffer".
12+
*
13+
* Re-wrapping the same backing buffer as a plain Uint8Array removes the Buffer subclass wrapper
14+
* while keeping the same underlying bytes. This creates a new view, not a byte copy, so the
15+
* overhead should be minimal.
16+
*/
17+
payload = new Uint8Array(payload.buffer, payload.byteOffset, payload.byteLength);
18+
}
19+
20+
return super.control(op, payload);
21+
}
22+
}

0 commit comments

Comments
 (0)