Skip to content

Commit

Permalink
Merge pull request #64 from IO-Design-Team/feature/wasm-int-warning
Browse files Browse the repository at this point in the history
WASM int warning
  • Loading branch information
Rexios80 authored Jan 6, 2025
2 parents cad6a65 + a815ce3 commit 8e0b7e3
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 11 deletions.
5 changes: 5 additions & 0 deletions hive/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 2.9.0

- Prints a warning when writing `int` or `List<int>` types in a WASM environment
- Only emits print statements when assertions are enabled (aka debug mode)

## 2.8.0+3

- Updates the commit hash for the transitive Hive dependencies workaround
Expand Down
7 changes: 4 additions & 3 deletions hive/lib/src/backend/js/native/backend_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:hive_ce/hive.dart';
import 'package:hive_ce/src/backend/js/native/storage_backend_js.dart';
import 'package:hive_ce/src/backend/js/native/utils.dart';
import 'package:hive_ce/src/backend/storage_backend.dart';
import 'package:hive_ce/src/util/debug_utils.dart';
import 'package:web/web.dart';

/// Opens IndexedDB databases
Expand Down Expand Up @@ -35,7 +36,7 @@ class BackendManager implements BackendManagerInterface {
// in case the objectStore is not contained, re-open the db and
// update version
if (!db.objectStoreNames.contains(objectStoreName)) {
print(
debugPrint(
'Creating objectStore $objectStoreName in database $databaseName...',
);
final request = indexedDB!.open(databaseName, db.version + 1);
Expand All @@ -48,14 +49,14 @@ class BackendManager implements BackendManagerInterface {
db = await request.asFuture<IDBDatabase>();
}

print('Got object store $objectStoreName in database $databaseName.');
debugPrint('Got object store $objectStoreName in database $databaseName.');

return StorageBackendJs(db, cipher, objectStoreName);
}

@override
Future<void> deleteBox(String name, String? path, String? collection) async {
print('Delete $name // $collection from disk');
debugPrint('Delete $name // $collection from disk');

// compatibility for old store format
final databaseName = collection ?? name;
Expand Down
26 changes: 25 additions & 1 deletion hive/lib/src/backend/js/native/storage_backend_js.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,29 @@ import 'package:hive_ce/src/binary/binary_writer_impl.dart';
import 'package:hive_ce/src/binary/frame.dart';
import 'package:hive_ce/src/box/keystore.dart';
import 'package:hive_ce/src/registry/type_registry_impl.dart';
import 'package:hive_ce/src/util/debug_utils.dart';
import 'package:meta/meta.dart';
import 'package:web/web.dart';

/// Handles all IndexedDB related tasks
class StorageBackendJs extends StorageBackend {
static const _bytePrefix = [0x90, 0xA9];

/// If this is a WASM environment
@visibleForTesting
static const isWasm = bool.fromEnvironment('dart.tool.dart2wasm');

/// Warning message printed when writing `int` values in a WASM environment
@visibleForTesting
static const wasmIntWarning =
'WARNING: You are writing a type of `int` or `List<int>` in a WASM '
'environment. This value will read as a `double` or `List<double>` '
'on subsequent app launches and need manually casted back to the correct '
'type. Ensure you are doing one of the following:\n'
' - (box.get(key) as num).toInt()\n'
' - (box.get(key) as List).cast<num>().map((e) => e.toInt()).toList()\n\n'
'Also consider using TypeAdapters since they automatically handle this.';

final IDBDatabase _db;
final HiveCipher? _cipher;

Expand Down Expand Up @@ -62,6 +79,13 @@ class StorageBackendJs extends StorageBackend {
value is List<num> ||
value is List<bool> ||
value is List<String>) {
ifDebug(() {
final isIntType = value is int || value is List<int>;
if (isIntType && isWasm) {
print(wasmIntWarning);
}
});

return value.jsify();
}
}
Expand Down Expand Up @@ -206,7 +230,7 @@ class StorageBackendJs extends StorageBackend {
Future<void> deleteFromDisk() async {
final indexDB = window.self.indexedDB;

print('Delete ${_db.name} // $objectStoreName from disk');
debugPrint('Delete ${_db.name} // $objectStoreName from disk');

// directly deleting the entire DB if a non-collection Box
if (_db.objectStoreNames.length == 1) {
Expand Down
3 changes: 2 additions & 1 deletion hive/lib/src/backend/vm/backend_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'dart:io';
import 'package:hive_ce/hive.dart';
import 'package:hive_ce/src/backend/storage_backend.dart';
import 'package:hive_ce/src/backend/vm/storage_backend_vm.dart';
import 'package:hive_ce/src/util/debug_utils.dart';
import 'package:meta/meta.dart';

/// Not part of public API
Expand Down Expand Up @@ -61,7 +62,7 @@ class BackendManager implements BackendManagerInterface {
}
return hiveFile;
} else if (await compactedFile.exists()) {
print('Restoring compacted file.');
debugPrint('Restoring compacted file.');
return await compactedFile.rename(hiveFile.path);
} else {
await hiveFile.create();
Expand Down
3 changes: 2 additions & 1 deletion hive/lib/src/backend/vm/storage_backend_vm.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'package:hive_ce/src/box/keystore.dart';
import 'package:hive_ce/src/io/buffered_file_reader.dart';
import 'package:hive_ce/src/io/buffered_file_writer.dart';
import 'package:hive_ce/src/io/frame_io_helper.dart';
import 'package:hive_ce/src/util/debug_utils.dart';
import 'package:meta/meta.dart';

/// Storage backend for the Dart VM
Expand Down Expand Up @@ -102,7 +103,7 @@ class StorageBackendVm extends StorageBackend {

if (recoveryOffset != -1) {
if (_crashRecovery) {
print('Recovering corrupted box.');
debugPrint('Recovering corrupted box.');
await writeRaf.truncate(recoveryOffset);
await writeRaf.setPosition(recoveryOffset);
writeOffset = recoveryOffset;
Expand Down
7 changes: 4 additions & 3 deletions hive/lib/src/registry/type_registry_impl.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:hive_ce/hive.dart';
import 'package:hive_ce/src/adapters/ignored_type_adapter.dart';
import 'package:hive_ce/src/util/debug_utils.dart';
import 'package:meta/meta.dart';

/// Not part of public API
Expand Down Expand Up @@ -107,7 +108,7 @@ class TypeRegistryImpl implements TypeRegistry {
bool override = false,
}) {
if (T == dynamic || T == Object) {
print(
debugPrint(
'Registering type adapters for dynamic type is must be avoided, '
'otherwise all the write requests to Hive will be handled by given '
'adapter. Please explicitly provide adapter type on registerAdapter '
Expand All @@ -130,7 +131,7 @@ class TypeRegistryImpl implements TypeRegistry {
final oldAdapterType = oldAdapter.runtimeType;
final newAdapterType = adapter.runtimeType;
final typeId = adapter.typeId;
print(
debugPrint(
'You are trying to override $oldAdapterType '
'with $newAdapterType for typeId: $typeId. '
'Please note that overriding adapters might '
Expand All @@ -151,7 +152,7 @@ class TypeRegistryImpl implements TypeRegistry {
final existingAdapterTypeId = adapterForSameType.typeId;

if (adapterTypeId != existingAdapterTypeId) {
print(
debugPrint(
'WARNING: You are trying to register $adapterType '
'(typeId $adapterTypeId) for type $T but there is already a '
'TypeAdapter for this type: $existingAdapterType '
Expand Down
10 changes: 10 additions & 0 deletions hive/lib/src/util/debug_utils.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/// Only run the given function if assertions are enabled
void ifDebug(void Function() f) {
assert(() {
f();
return true;
}());
}

/// Only print the given message if assertions are enabled
void debugPrint(String message) => ifDebug(() => print(message));
2 changes: 1 addition & 1 deletion hive/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: hive_ce
description: Hive Community Edition - A spiritual continuation of Hive v2
version: 2.8.0+3
version: 2.9.0
homepage: https://github.com/IO-Design-Team/hive_ce/tree/main/hive
documentation: https://docs.hivedb.dev/

Expand Down
27 changes: 26 additions & 1 deletion hive/test/tests/backend/js/storage_backend_js_test.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@TestOn('browser')
library;

import 'dart:async' show Future;
import 'dart:async';
import 'dart:js_interop';
import 'dart:typed_data';

Expand Down Expand Up @@ -117,6 +117,31 @@ void main() async {
expect(encoded, [0x90, 0xA9, ...writer.toBytes()]);
});
});

group('int', () {
void expectWarning(Object obj) {
var output = '';
runZoned(
() => _getBackend().encodeValue(Frame('key', obj)),
zoneSpecification: ZoneSpecification(
print: (_, __, ___, line) => output += line,
),
);

if (StorageBackendJs.isWasm) {
expect(output, StorageBackendJs.wasmIntWarning);
} else {
expect(output, isEmpty);
}
}

test('prints warning for `int` type', () => expectWarning(11));

test(
'prints warning for `List<int>` type',
() => expectWarning([11, 12, 13]),
);
});
});

group('.decodeValue()', () {
Expand Down

0 comments on commit 8e0b7e3

Please sign in to comment.