From 891f72d9a3978292354bf057628878b7b607a28e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Mon, 11 Mar 2024 20:52:55 +0100 Subject: [PATCH 01/68] Refactor handles subscription.dart --- .../realm_dart/lib/src/native/convert.dart | 17 + .../lib/src/native/error_handling.dart | 60 ++ .../mutable_subscription_set_handle.dart | 70 ++ .../realm_dart/lib/src/native/realm_core.dart | 601 ++++++------------ .../lib/src/native/subscription_handle.dart | 22 + .../src/native/subscription_set_handle.dart | 66 ++ packages/realm_dart/lib/src/realm_class.dart | 2 +- packages/realm_dart/lib/src/subscription.dart | 91 +-- 8 files changed, 455 insertions(+), 474 deletions(-) create mode 100644 packages/realm_dart/lib/src/native/convert.dart create mode 100644 packages/realm_dart/lib/src/native/error_handling.dart create mode 100644 packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart create mode 100644 packages/realm_dart/lib/src/native/subscription_handle.dart create mode 100644 packages/realm_dart/lib/src/native/subscription_set_handle.dart diff --git a/packages/realm_dart/lib/src/native/convert.dart b/packages/realm_dart/lib/src/native/convert.dart new file mode 100644 index 000000000..ae0c3f7cc --- /dev/null +++ b/packages/realm_dart/lib/src/native/convert.dart @@ -0,0 +1,17 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + +part of 'realm_core.dart'; + +extension HandleBaseEx on T { + T? get nullPtrAsNull => _pointer == nullptr ? null : this; + U? convert(U Function(T) convertor) => nullPtrAsNull.convert(convertor); +} + +extension NullableObjectEx on T? { + U? convert(U Function(T) convertor) { + final self = this; + if (self == null) return null; + return convertor(self); + } +} diff --git a/packages/realm_dart/lib/src/native/error_handling.dart b/packages/realm_dart/lib/src/native/error_handling.dart new file mode 100644 index 000000000..f18c9145d --- /dev/null +++ b/packages/realm_dart/lib/src/native/error_handling.dart @@ -0,0 +1,60 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + +part of 'realm_core.dart'; + +void invokeGetBool(bool Function() callback, [String? errorMessage]) { + bool success = callback(); + if (!success) { + throwLastError(errorMessage); + } +} + +Pointer invokeGetPointer(Pointer Function() callback, [String? errorMessage]) { + final result = callback(); + if (result == nullptr) { + throwLastError(errorMessage); + } + return result; +} + +class LastError { + final int code; + final String? message; + final Object? userError; + + LastError(this.code, [this.message, this.userError]); + + @override + String toString() => "${message ?? 'No message'}. Error code: $code."; +} + +LastError? getLastError(Allocator allocator) { + final error = allocator(); + final success = _realmLib.realm_get_last_error(error); + return success ? error.ref.toDart() : null; +} + +Never throwLastError([String? errorMessage]) { + using((Arena arena) { + final lastError = getLastError(arena); + if (lastError?.userError != null) { + throw UserCallbackException(lastError!.userError!); + } + + final message = '${errorMessage != null ? "$errorMessage. " : ""}${lastError ?? ""}'; + switch (lastError?.code) { + case realm_errno.RLM_ERR_SCHEMA_MISMATCH: + throw MigrationRequiredException(message); + default: + throw RealmException(message); + } + }); +} + +extension on realm_error { + LastError toDart() { + final message = this.message.cast().toRealmDartString(); + return LastError(error, message, user_code_error.toUserCodeError()); + } +} diff --git a/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart b/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart new file mode 100644 index 000000000..4da103287 --- /dev/null +++ b/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart @@ -0,0 +1,70 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + +part of 'realm_core.dart'; + +class MutableSubscriptionSetHandle extends SubscriptionSetHandle { + MutableSubscriptionSetHandle._(Pointer pointer, RealmHandle root) : super._(pointer.cast(), root); + + Pointer get _mutablePointer => super._pointer.cast(); + + SubscriptionSetHandle commit() => SubscriptionSetHandle._(invokeGetPointer(() => _realmLib.realm_sync_subscription_set_commit(_mutablePointer)), _root); + + SubscriptionHandle insertOrAssignSubscription(RealmResults results, String? name, bool update) { + if (!update) { + if (name != null && findByName(name) != null) { + throw RealmException('Duplicate subscription with name: $name'); + } + } + return using((arena) { + final outIndex = arena(); + final outInserted = arena(); + invokeGetBool(() => _realmLib.realm_sync_subscription_set_insert_or_assign_results( + _mutablePointer, + results.handle._pointer, + name?.toCharPtr(arena) ?? nullptr, + outIndex, + outInserted, + )); + return this[outIndex.value]; + }); + } + + bool erase(Subscription subscription) { + return using((arena) { + final outErased = arena(); + invokeGetBool(() => _realmLib.realm_sync_subscription_set_erase_by_id( + _mutablePointer, + subscription.id.toNative(arena), + outErased, + )); + return outErased.value; + }); + } + + bool eraseByName(String name) { + return using((arena) { + final outErased = arena(); + invokeGetBool(() => _realmLib.realm_sync_subscription_set_erase_by_name( + _mutablePointer, + name.toCharPtr(arena), + outErased, + )); + return outErased.value; + }); + } + + bool eraseByResults(RealmResults results) { + return using((arena) { + final outErased = arena(); + invokeGetBool(() => _realmLib.realm_sync_subscription_set_erase_by_results( + _mutablePointer, + results.handle._pointer, + outErased, + )); + return outErased.value; + }); + } + + void clear() => invokeGetBool(() => _realmLib.realm_sync_subscription_set_clear(_mutablePointer)); +} diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index a8415d76a..c7ad4edf4 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -14,11 +14,11 @@ import 'package:cancellation_token/cancellation_token.dart'; import 'package:crypto/crypto.dart'; // Hide StringUtf8Pointer.toNativeUtf8 and StringUtf16Pointer since these allows silently allocating memory. Use toUtf8Ptr instead import 'package:ffi/ffi.dart' hide StringUtf8Pointer, StringUtf16Pointer; +import 'package:logging/logging.dart'; import 'package:path/path.dart' as path; import 'package:pubspec_parse/pubspec_parse.dart'; import 'package:realm_common/realm_common.dart' as common show Decimal128; import 'package:realm_common/realm_common.dart' hide Decimal128; -import 'package:realm_dart/src/logging.dart'; import '../app.dart'; import '../collections.dart'; @@ -39,6 +39,11 @@ import '../user.dart'; import 'realm_bindings.dart'; part 'decimal128.dart'; +part 'error_handling.dart'; // TODO: Use regular import +part 'convert.dart'; +part 'subscription_handle.dart'; +part 'subscription_set_handle.dart'; +part 'mutable_subscription_set_handle.dart'; const bugInTheSdkMessage = "This is likely a bug in the Realm SDK - please file an issue at https://github.com/realm/realm-dart/issues"; @@ -117,33 +122,6 @@ class _RealmCore { // _realmLib.realm_dart_gc(); // } - LastError? getLastError(Allocator allocator) { - final error = allocator(); - final success = _realmLib.realm_get_last_error(error); - if (!success) { - return null; - } - - return error.ref.toLastError(); - } - - void throwLastError([String? errorMessage]) { - using((Arena arena) { - final lastError = getLastError(arena); - if (lastError?.userError != null) { - throw UserCallbackException(lastError!.userError!); - } - - final message = '${errorMessage != null ? "$errorMessage. " : ""}${lastError ?? ""}'; - switch (lastError?.code) { - case realm_errno.RLM_ERR_SCHEMA_MISMATCH: - throw MigrationRequiredException(message); - default: - throw RealmException(message); - } - }); - } - SchemaHandle _createSchema(Iterable schema) { return using((Arena arena) { final classCount = schema.length; @@ -203,7 +181,7 @@ class _RealmCore { schemaProperties.elementAt(i).value = properties; } - final schemaPtr = _realmLib.invokeGetPointer(() => _realmLib.realm_schema_new(schemaClasses, classCount, schemaProperties)); + final schemaPtr = invokeGetPointer(() => _realmLib.realm_schema_new(schemaClasses, classCount, schemaProperties)); return SchemaHandle._(schemaPtr); }); } @@ -275,7 +253,7 @@ class _RealmCore { _realmLib.realm_config_set_in_memory(configHandle._pointer, true); } else if (config is FlexibleSyncConfiguration) { _realmLib.realm_config_set_schema_mode(configHandle._pointer, realm_schema_mode.RLM_SCHEMA_MODE_ADDITIVE_DISCOVERED); - final syncConfigPtr = _realmLib.invokeGetPointer(() => _realmLib.realm_flx_sync_config_new(config.user.handle._pointer)); + final syncConfigPtr = invokeGetPointer(() => _realmLib.realm_flx_sync_config_new(config.user.handle._pointer)); try { _realmLib.realm_sync_config_set_session_stop_policy(syncConfigPtr, config.sessionStopPolicy.index); _realmLib.realm_sync_config_set_resync_mode(syncConfigPtr, config.clientResetHandler.clientResyncMode.index); @@ -335,7 +313,7 @@ class _RealmCore { } String getPathForUser(User user) { - final syncConfigPtr = _realmLib.invokeGetPointer(() => _realmLib.realm_flx_sync_config_new(user.handle._pointer)); + final syncConfigPtr = invokeGetPointer(() => _realmLib.realm_flx_sync_config_new(user.handle._pointer)); try { final path = _realmLib.realm_app_sync_client_get_default_file_path_for_realm(syncConfigPtr, nullptr); return path.cast().toRealmDartString(freeRealmMemory: true)!; @@ -344,178 +322,8 @@ class _RealmCore { } } - ObjectId subscriptionId(Subscription subscription) { - final id = _realmLib.realm_sync_subscription_id(subscription.handle._pointer); - return id.toDart(); - } - - String? subscriptionName(Subscription subscription) { - final name = _realmLib.realm_sync_subscription_name(subscription.handle._pointer); - return name.toDart(); - } - - String subscriptionObjectClassName(Subscription subscription) { - final objectClassName = _realmLib.realm_sync_subscription_object_class_name(subscription.handle._pointer); - return objectClassName.toDart()!; - } - - String subscriptionQueryString(Subscription subscription) { - final queryString = _realmLib.realm_sync_subscription_query_string(subscription.handle._pointer); - return queryString.toDart()!; - } - - DateTime subscriptionCreatedAt(Subscription subscription) { - final createdAt = _realmLib.realm_sync_subscription_created_at(subscription.handle._pointer); - return createdAt.toDart(); - } - - DateTime subscriptionUpdatedAt(Subscription subscription) { - final updatedAt = _realmLib.realm_sync_subscription_updated_at(subscription.handle._pointer); - return updatedAt.toDart(); - } - SubscriptionSetHandle getSubscriptions(Realm realm) { - return SubscriptionSetHandle._(_realmLib.invokeGetPointer(() => _realmLib.realm_sync_get_active_subscription_set(realm.handle._pointer)), realm.handle); - } - - void refreshSubscriptions(SubscriptionSet subscriptions) { - _realmLib.invokeGetBool(() => _realmLib.realm_sync_subscription_set_refresh(subscriptions.handle._pointer)); - } - - int getSubscriptionSetSize(SubscriptionSet subscriptions) { - return _realmLib.realm_sync_subscription_set_size(subscriptions.handle._pointer); - } - - Exception? getSubscriptionSetError(SubscriptionSet subscriptions) { - final error = _realmLib.realm_sync_subscription_set_error_str(subscriptions.handle._pointer); - final message = error.cast().toRealmDartString(treatEmptyAsNull: true); - return message == null ? null : RealmException(message); - } - - SubscriptionHandle subscriptionAt(SubscriptionSet subscriptions, int index) { - return SubscriptionHandle._(_realmLib.invokeGetPointer(() => _realmLib.realm_sync_subscription_at( - subscriptions.handle._pointer, - index, - ))); - } - - SubscriptionHandle? findSubscriptionByName(SubscriptionSet subscriptions, String name) { - return using((arena) { - final result = _realmLib.realm_sync_find_subscription_by_name( - subscriptions.handle._pointer, - name.toCharPtr(arena), - ); - return result == nullptr ? null : SubscriptionHandle._(result); - }); - } - - SubscriptionHandle? findSubscriptionByResults(SubscriptionSet subscriptions, RealmResults results) { - final result = _realmLib.realm_sync_find_subscription_by_results( - subscriptions.handle._pointer, - results.handle._pointer, - ); - return result == nullptr ? null : SubscriptionHandle._(result); - } - - static void _stateChangeCallback(Object userdata, int state) { - final completer = userdata as CancellableCompleter; - if (!completer.isCancelled) { - completer.complete(SubscriptionSetState.values[state]); - } - } - - Future waitForSubscriptionSetStateChange(SubscriptionSet subscriptions, SubscriptionSetState notifyWhen, - [CancellationToken? cancellationToken]) { - final completer = CancellableCompleter(cancellationToken); - if (!completer.isCancelled) { - final callback = Pointer.fromFunction(_stateChangeCallback); - final userdata = _realmLib.realm_dart_userdata_async_new(completer, callback.cast(), scheduler.handle._pointer); - _realmLib.realm_sync_on_subscription_set_state_change_async(subscriptions.handle._pointer, notifyWhen.index, - _realmLib.addresses.realm_dart_sync_on_subscription_state_changed_callback, userdata.cast(), _realmLib.addresses.realm_dart_userdata_async_free); - } - return completer.future; - } - - int subscriptionSetGetVersion(SubscriptionSet subscriptions) { - return _realmLib.realm_sync_subscription_set_version(subscriptions.handle._pointer); - } - - SubscriptionSetState subscriptionSetGetState(SubscriptionSet subscriptions) { - return SubscriptionSetState.values[_realmLib.realm_sync_subscription_set_state(subscriptions.handle._pointer)]; - } - - MutableSubscriptionSetHandle subscriptionSetMakeMutable(SubscriptionSet subscriptions) { - return MutableSubscriptionSetHandle._( - _realmLib.invokeGetPointer(() => _realmLib.realm_sync_make_subscription_set_mutable(subscriptions.handle._pointer)), subscriptions.realm.handle); - } - - SubscriptionSetHandle subscriptionSetCommit(MutableSubscriptionSet subscriptions) { - return SubscriptionSetHandle._( - _realmLib.invokeGetPointer(() => _realmLib.realm_sync_subscription_set_commit(subscriptions.handle._mutablePointer)), subscriptions.realm.handle); - } - - SubscriptionHandle insertOrAssignSubscription(MutableSubscriptionSet subscriptions, RealmResults results, String? name, bool update) { - if (!update) { - if (name != null && findSubscriptionByName(subscriptions, name) != null) { - throw RealmException('Duplicate subscription with name: $name'); - } - } - return using((arena) { - final out_index = arena(); - final out_inserted = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_sync_subscription_set_insert_or_assign_results( - subscriptions.handle._mutablePointer, - results.handle._pointer, - name?.toCharPtr(arena) ?? nullptr, - out_index, - out_inserted, - )); - return subscriptionAt(subscriptions, out_index.value); - }); - } - - bool eraseSubscriptionById(MutableSubscriptionSet subscriptions, Subscription subscription) { - return using((arena) { - final out_found = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_sync_subscription_set_erase_by_id( - subscriptions.handle._mutablePointer, - subscription.id.toNative(arena), - out_found, - )); - return out_found.value; - }); - } - - bool eraseSubscriptionByName(MutableSubscriptionSet subscriptions, String name) { - return using((arena) { - final out_found = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_sync_subscription_set_erase_by_name( - subscriptions.handle._mutablePointer, - name.toCharPtr(arena), - out_found, - )); - return out_found.value; - }); - } - - bool eraseSubscriptionByResults(MutableSubscriptionSet subscriptions, RealmResults results) { - return using((arena) { - final out_found = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_sync_subscription_set_erase_by_results( - subscriptions.handle._mutablePointer, - results.handle._pointer, - out_found, - )); - return out_found.value; - }); - } - - void clearSubscriptionSet(MutableSubscriptionSet subscriptions) { - _realmLib.invokeGetBool(() => _realmLib.realm_sync_subscription_set_clear(subscriptions.handle._mutablePointer)); - } - - void refreshSubscriptionSet(SubscriptionSet subscriptions) { - _realmLib.invokeGetBool(() => _realmLib.realm_sync_subscription_set_refresh(subscriptions.handle._pointer)); + return SubscriptionSetHandle._(invokeGetPointer(() => _realmLib.realm_sync_get_active_subscription_set(realm.handle._pointer)), realm.handle); } static bool initial_data_callback(Pointer userdata, Pointer realmPtr) { @@ -575,7 +383,7 @@ class _RealmCore { static void _syncErrorHandlerCallback(Object userdata, Pointer session, realm_sync_error error) { final syncConfig = userdata as FlexibleSyncConfiguration; // TODO: Take the app from the session instead of from syncConfig after fixing issue https://github.com/realm/realm-dart/issues/633 - final syncError = SyncErrorInternal.createSyncError(error.toSyncErrorDetails(), app: syncConfig.user.app); + final syncError = SyncErrorInternal.createSyncError(error.toDart(), app: syncConfig.user.app); if (syncError is ClientResetError) { syncConfig.clientResetHandler.onManualReset?.call(syncError); @@ -621,7 +429,7 @@ class _RealmCore { } final beforeRealm = RealmInternal.getUnowned(syncConfig, RealmHandle._unowned(beforeHandle)); - final realmPtr = _realmLib.invokeGetPointer(() => _realmLib.realm_from_thread_safe_reference(afterReference, scheduler.handle._pointer)); + final realmPtr = invokeGetPointer(() => _realmLib.realm_from_thread_safe_reference(afterReference, scheduler.handle._pointer)); final afterRealm = RealmInternal.getUnowned(syncConfig, RealmHandle._unowned(realmPtr)); try { @@ -656,14 +464,13 @@ class _RealmCore { RealmHandle openRealm(Configuration config) { final configHandle = _createConfig(config); - final realmPtr = _realmLib.invokeGetPointer(() => _realmLib.realm_open(configHandle._pointer), "Error opening realm at path ${config.path}"); + final realmPtr = invokeGetPointer(() => _realmLib.realm_open(configHandle._pointer), "Error opening realm at path ${config.path}"); return RealmHandle._(realmPtr); } RealmAsyncOpenTaskHandle createRealmAsyncOpenTask(FlexibleSyncConfiguration config) { final configHandle = _createConfig(config); - final asyncOpenTaskPtr = - _realmLib.invokeGetPointer(() => _realmLib.realm_open_synchronized(configHandle._pointer), "Error opening realm at path ${config.path}"); + final asyncOpenTaskPtr = invokeGetPointer(() => _realmLib.realm_open_synchronized(configHandle._pointer), "Error opening realm at path ${config.path}"); return RealmAsyncOpenTaskHandle._(asyncOpenTaskPtr); } @@ -691,12 +498,12 @@ class _RealmCore { } if (error != nullptr) { final err = arena(); - final lastError = _realmLib.realm_get_async_error(error, err) ? err.ref.toLastError() : null; + final lastError = _realmLib.realm_get_async_error(error, err) ? err.ref.toDart() : null; completer.completeError(RealmException("Failed to open realm: ${lastError?.message ?? 'Error details missing.'}")); return; } - final realmPtr = _realmLib.invokeGetPointer(() => _realmLib.realm_from_thread_safe_reference(realmSafePtr, scheduler.handle._pointer)); + final realmPtr = invokeGetPointer(() => _realmLib.realm_from_thread_safe_reference(realmSafePtr, scheduler.handle._pointer)); completer.complete(RealmHandle._(realmPtr)); }); } @@ -709,7 +516,7 @@ class _RealmCore { RealmAsyncOpenTaskHandle handle, RealmAsyncOpenProgressNotificationsController controller) { final callback = Pointer.fromFunction(_syncProgressCallback); final userdata = _realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle._pointer); - final tokenPtr = _realmLib.invokeGetPointer(() => _realmLib.realm_async_open_task_register_download_progress_notifier( + final tokenPtr = invokeGetPointer(() => _realmLib.realm_async_open_task_register_download_progress_notifier( handle._pointer, _realmLib.addresses.realm_dart_sync_progress_callback, userdata.cast(), @@ -727,7 +534,7 @@ class _RealmCore { RealmSchema _readSchema(Realm realm, Arena arena, {int expectedSize = 10}) { final classesPtr = arena(expectedSize); final actualCount = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_get_class_keys(realm.handle._pointer, classesPtr, expectedSize, actualCount)); + invokeGetBool(() => _realmLib.realm_get_class_keys(realm.handle._pointer, classesPtr, expectedSize, actualCount)); if (expectedSize < actualCount.value) { arena.free(classesPtr); return _readSchema(realm, arena, expectedSize: actualCount.value); @@ -737,7 +544,7 @@ class _RealmCore { for (var i = 0; i < actualCount.value; i++) { final classInfo = arena(); final classKey = classesPtr.elementAt(i).value; - _realmLib.invokeGetBool(() => _realmLib.realm_get_class(realm.handle._pointer, classKey, classInfo)); + invokeGetBool(() => _realmLib.realm_get_class(realm.handle._pointer, classKey, classInfo)); final name = classInfo.ref.name.cast().toDartString(); final baseType = ObjectType.values.firstWhere((element) => element.flags == classInfo.ref.flags, @@ -753,7 +560,7 @@ class _RealmCore { SchemaObject _getSchemaForClassKey(Realm realm, int classKey, String name, ObjectType baseType, Arena arena, {int expectedSize = 10}) { final actualCount = arena(); final propertiesPtr = arena(expectedSize); - _realmLib.invokeGetBool(() => _realmLib.realm_get_class_properties(realm.handle._pointer, classKey, propertiesPtr, expectedSize, actualCount)); + invokeGetBool(() => _realmLib.realm_get_class_properties(realm.handle._pointer, classKey, propertiesPtr, expectedSize, actualCount)); if (expectedSize < actualCount.value) { // The supplied array was too small - resize it @@ -788,7 +595,7 @@ class _RealmCore { void deleteRealmFiles(String path) { using((Arena arena) { final realm_deleted = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_delete_files(path.toCharPtr(arena), realm_deleted), "Error deleting realm at path $path"); + invokeGetBool(() => _realmLib.realm_delete_files(path.toCharPtr(arena), realm_deleted), "Error deleting realm at path $path"); }); } @@ -817,7 +624,7 @@ class _RealmCore { } void closeRealm(Realm realm) { - _realmLib.invokeGetBool(() => _realmLib.realm_close(realm.handle._pointer), "Realm close failed"); + invokeGetBool(() => _realmLib.realm_close(realm.handle._pointer), "Realm close failed"); } bool isRealmClosed(Realm realm) { @@ -825,11 +632,11 @@ class _RealmCore { } void beginWrite(Realm realm) { - _realmLib.invokeGetBool(() => _realmLib.realm_begin_write(realm.handle._pointer), "Could not begin write"); + invokeGetBool(() => _realmLib.realm_begin_write(realm.handle._pointer), "Could not begin write"); } void commitWrite(Realm realm) { - _realmLib.invokeGetBool(() => _realmLib.realm_commit(realm.handle._pointer), "Could not commit write"); + invokeGetBool(() => _realmLib.realm_commit(realm.handle._pointer), "Could not commit write"); } Future beginWriteAsync(Realm realm, CancellationToken? ct) { @@ -842,7 +649,7 @@ class _RealmCore { if (ct?.isCancelled != true) { using((arena) { final transaction_id = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_async_begin_write( + invokeGetBool(() => _realmLib.realm_async_begin_write( realm.handle._pointer, Pointer.fromFunction(_completeAsyncBeginWrite), completer.toPersistentHandle(), @@ -866,7 +673,7 @@ class _RealmCore { if (ct?.isCancelled != true) { using((arena) { final transaction_id = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_async_commit( + invokeGetBool(() => _realmLib.realm_async_commit( realm.handle._pointer, Pointer.fromFunction(_completeAsyncCommit), completer.toPersistentHandle(), @@ -883,7 +690,7 @@ class _RealmCore { bool _cancelAsync(Realm realm, int cancellationId) { return using((Arena arena) { final didCancel = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_async_cancel(realm.handle._pointer, cancellationId, didCancel)); + invokeGetBool(() => _realmLib.realm_async_cancel(realm.handle._pointer, cancellationId, didCancel)); return didCancel.value; }); } @@ -907,13 +714,13 @@ class _RealmCore { } void rollbackWrite(Realm realm) { - _realmLib.invokeGetBool(() => _realmLib.realm_rollback(realm.handle._pointer), "Could not rollback write"); + invokeGetBool(() => _realmLib.realm_rollback(realm.handle._pointer), "Could not rollback write"); } bool realmRefresh(Realm realm) { return using((Arena arena) { final did_refresh = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_refresh(realm.handle._pointer, did_refresh), "Could not refresh"); + invokeGetBool(() => _realmLib.realm_refresh(realm.handle._pointer, did_refresh), "Could not refresh"); return did_refresh.value; }); } @@ -945,7 +752,7 @@ class _RealmCore { return using((Arena arena) { final found = arena(); final classInfo = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_find_class(realm.handle._pointer, schema.name.toCharPtr(arena), found, classInfo), + invokeGetBool(() => _realmLib.realm_find_class(realm.handle._pointer, schema.name.toCharPtr(arena), found, classInfo), "Error getting class ${schema.name} from realm at ${realm.config.path}"); if (!found.value) { @@ -999,11 +806,15 @@ class _RealmCore { return RealmObjectHandle._(objectPtr, obj.realm.handle); } + RealmObjectHandle createRealmObject(Realm realm, int classKey) => RealmObjectHandle.create(realm.handle, classKey); + + RealmObjectHandle createEmbeddedObject(RealmObjectBase obj, int propertyKey) => RealmObjectHandle.createEmbedded(obj.handle, propertyKey); + Tuple getEmbeddedParent(EmbeddedObject obj) { return using((Arena arena) { final parentPtr = arena>(); final classKeyPtr = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_object_get_parent(obj.handle._pointer, parentPtr, classKeyPtr)); + invokeGetBool(() => _realmLib.realm_object_get_parent(obj.handle._pointer, parentPtr, classKeyPtr)); final handle = RealmObjectHandle._(parentPtr.value, obj.realm.handle); @@ -1015,32 +826,16 @@ class _RealmCore { return _realmLib.realm_object_get_table(handle._pointer); } - RealmObjectHandle getOrCreateRealmObjectWithPrimaryKey(Realm realm, int classKey, Object? primaryKey) { - return using((Arena arena) { - final realm_value = _toRealmValue(primaryKey, arena); - final didCreate = arena(); - final realmPtr = _realmLib.invokeGetPointer(() => _realmLib.realm_object_get_or_create_with_primary_key( - realm.handle._pointer, - classKey, - realm_value.ref, - didCreate, - )); - return RealmObjectHandle._(realmPtr, realm.handle); - }); - } + RealmObjectHandle getOrCreateRealmObjectWithPrimaryKey(Realm realm, int classKey, Object? primaryKey) => + RealmObjectHandle.getOrCreateWithPrimaryKey(realm.handle, classKey, primaryKey); - RealmObjectHandle createRealmObjectWithPrimaryKey(Realm realm, int classKey, Object? primaryKey) { - return using((Arena arena) { - final realm_value = _toRealmValue(primaryKey, arena); - final realmPtr = _realmLib.invokeGetPointer(() => _realmLib.realm_object_create_with_primary_key(realm.handle._pointer, classKey, realm_value.ref)); - return RealmObjectHandle._(realmPtr, realm.handle); - }); - } + RealmObjectHandle createRealmObjectWithPrimaryKey(Realm realm, int classKey, Object? primaryKey) => + RealmObjectHandle.createWithPrimaryKey(realm.handle, classKey, primaryKey); Object? getProperty(RealmObjectBase object, int propertyKey) { return using((Arena arena) { final realm_value = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_get_value(object.handle._pointer, propertyKey, realm_value)); + invokeGetBool(() => _realmLib.realm_get_value(object.handle._pointer, propertyKey, realm_value)); return realm_value.toDartValue(object.realm, () => _realmLib.realm_get_list(object.handle._pointer, propertyKey), () => _realmLib.realm_get_dictionary(object.handle._pointer, propertyKey)); }); @@ -1049,7 +844,7 @@ class _RealmCore { void setProperty(RealmObjectBase object, int propertyKey, Object? value, bool isDefault) { using((Arena arena) { final realm_value = _toRealmValue(value, arena); - _realmLib.invokeGetBool(() => _realmLib.realm_set_value(object.handle._pointer, propertyKey, realm_value.ref, isDefault)); + invokeGetBool(() => _realmLib.realm_set_value(object.handle._pointer, propertyKey, realm_value.ref, isDefault)); }); } @@ -1080,13 +875,13 @@ class _RealmCore { RealmObjectHandle? findExisting(Realm realm, int classKey, RealmObjectHandle other) { final key = _realmLib.realm_object_get_key(other._pointer); - final pointer = _realmLib.invokeGetPointer(() => _realmLib.realm_get_object(realm.handle._pointer, classKey, key)); + final pointer = invokeGetPointer(() => _realmLib.realm_get_object(realm.handle._pointer, classKey, key)); return RealmObjectHandle._(pointer, realm.handle); } void renameProperty(Realm realm, String objectType, String oldName, String newName, SchemaHandle schema) { using((Arena arena) { - _realmLib.invokeGetBool(() => _realmLib.realm_schema_rename_property( + invokeGetBool(() => _realmLib.realm_schema_rename_property( realm.handle._pointer, schema._pointer, objectType.toCharPtr(arena), oldName.toCharPtr(arena), newName.toCharPtr(arena))); }); } @@ -1094,17 +889,17 @@ class _RealmCore { bool deleteType(Realm realm, String objectType) { return using((Arena arena) { final deletedPtr = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_remove_table(realm.handle._pointer, objectType.toCharPtr(arena), deletedPtr)); + invokeGetBool(() => _realmLib.realm_remove_table(realm.handle._pointer, objectType.toCharPtr(arena), deletedPtr)); return deletedPtr.value; }); } void deleteRealmObject(RealmObjectBase object) { - _realmLib.invokeGetBool(() => _realmLib.realm_object_delete(object.handle._pointer)); + invokeGetBool(() => _realmLib.realm_object_delete(object.handle._pointer)); } RealmResultsHandle findAll(Realm realm, int classKey) { - final pointer = _realmLib.invokeGetPointer(() => _realmLib.realm_object_find_all(realm.handle._pointer, classKey)); + final pointer = invokeGetPointer(() => _realmLib.realm_object_find_all(realm.handle._pointer, classKey)); return RealmResultsHandle._(pointer, realm.handle); } @@ -1116,7 +911,7 @@ class _RealmCore { _intoRealmQueryArg(args[i], argsPointer.elementAt(i), arena); } final queryHandle = _RealmQueryHandle._( - _realmLib.invokeGetPointer( + invokeGetPointer( () => _realmLib.realm_query_parse( realm.handle._pointer, classKey, @@ -1138,7 +933,7 @@ class _RealmCore { _intoRealmQueryArg(args[i], argsPointer.elementAt(i), arena); } final queryHandle = _RealmQueryHandle._( - _realmLib.invokeGetPointer( + invokeGetPointer( () => _realmLib.realm_query_parse_for_results( target.handle._pointer, query.toCharPtr(arena), @@ -1153,7 +948,7 @@ class _RealmCore { RealmResultsHandle _queryFindAll(_RealmQueryHandle queryHandle) { try { - final resultsPointer = _realmLib.invokeGetPointer(() => _realmLib.realm_query_find_all(queryHandle._pointer)); + final resultsPointer = invokeGetPointer(() => _realmLib.realm_query_find_all(queryHandle._pointer)); return RealmResultsHandle._(resultsPointer, queryHandle._root); } finally { queryHandle.release(); @@ -1168,7 +963,7 @@ class _RealmCore { _intoRealmQueryArg(args[i], argsPointer.elementAt(i), arena); } final queryHandle = _RealmQueryHandle._( - _realmLib.invokeGetPointer( + invokeGetPointer( () => _realmLib.realm_query_parse_for_list( target.handle._pointer, query.toCharPtr(arena), @@ -1189,7 +984,7 @@ class _RealmCore { _intoRealmQueryArg(args[i], argsPointer.elementAt(i), arena); } final queryHandle = _RealmQueryHandle._( - _realmLib.invokeGetPointer( + invokeGetPointer( () => _realmLib.realm_query_parse_for_set( target.handle._pointer, query.toCharPtr(arena), @@ -1212,7 +1007,7 @@ class _RealmCore { final results = mapGetValues(target); final queryHandle = _RealmQueryHandle._( - _realmLib.invokeGetPointer( + invokeGetPointer( () => _realmLib.realm_query_parse_for_results( results._pointer, query.toCharPtr(arena), @@ -1226,19 +1021,19 @@ class _RealmCore { } RealmResultsHandle resultsFromList(RealmList list) { - final pointer = _realmLib.invokeGetPointer(() => _realmLib.realm_list_to_results(list.handle._pointer)); + final pointer = invokeGetPointer(() => _realmLib.realm_list_to_results(list.handle._pointer)); return RealmResultsHandle._(pointer, list.realm.handle); } RealmResultsHandle resultsFromSet(RealmSet set) { - final pointer = _realmLib.invokeGetPointer(() => _realmLib.realm_set_to_results(set.handle._pointer)); + final pointer = invokeGetPointer(() => _realmLib.realm_set_to_results(set.handle._pointer)); return RealmResultsHandle._(pointer, set.realm.handle); } Object? resultsGetElementAt(RealmResults results, int index) { return using((Arena arena) { final realm_value = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_results_get(results.handle._pointer, index, realm_value)); + invokeGetBool(() => _realmLib.realm_results_get(results.handle._pointer, index, realm_value)); return realm_value.toDartValue(results.realm, () => _realmLib.realm_results_get_list(results.handle._pointer, index), () => _realmLib.realm_results_get_dictionary(results.handle._pointer, index)); }); @@ -1251,7 +1046,7 @@ class _RealmCore { // TODO: how should this behave for collections final realm_value = _toRealmValue(value, arena); - _realmLib.invokeGetBool( + invokeGetBool( () => _realmLib.realm_results_find( results.handle._pointer, realm_value, @@ -1264,14 +1059,14 @@ class _RealmCore { } RealmObjectHandle resultsGetObjectAt(RealmResults results, int index) { - final pointer = _realmLib.invokeGetPointer(() => _realmLib.realm_results_get_object(results.handle._pointer, index)); + final pointer = invokeGetPointer(() => _realmLib.realm_results_get_object(results.handle._pointer, index)); return RealmObjectHandle._(pointer, results.realm.handle); } int getResultsCount(RealmResults results) { return using((Arena arena) { final countPtr = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_results_count(results.handle._pointer, countPtr)); + invokeGetBool(() => _realmLib.realm_results_count(results.handle._pointer, countPtr)); return countPtr.value; }); } @@ -1279,7 +1074,7 @@ class _RealmCore { bool resultsIsValid(RealmResults results) { return using((arena) { final is_valid = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_results_is_valid(results.handle._pointer, is_valid)); + invokeGetBool(() => _realmLib.realm_results_is_valid(results.handle._pointer, is_valid)); return is_valid.value; }); } @@ -1391,24 +1186,24 @@ class _RealmCore { } RealmObjectHandle _getObject(Realm realm, int classKey, int objectKey) { - final pointer = _realmLib.invokeGetPointer(() => _realmLib.realm_get_object(realm.handle._pointer, classKey, objectKey)); + final pointer = invokeGetPointer(() => _realmLib.realm_get_object(realm.handle._pointer, classKey, objectKey)); return RealmObjectHandle._(pointer, realm.handle); } RealmListHandle getListProperty(RealmObjectBase object, int propertyKey) { - final pointer = _realmLib.invokeGetPointer(() => _realmLib.realm_get_list(object.handle._pointer, propertyKey)); + final pointer = invokeGetPointer(() => _realmLib.realm_get_list(object.handle._pointer, propertyKey)); return RealmListHandle._(pointer, object.realm.handle); } RealmResultsHandle getBacklinks(RealmObjectBase object, int sourceTableKey, int propertyKey) { - final pointer = _realmLib.invokeGetPointer(() => _realmLib.realm_get_backlinks(object.handle._pointer, sourceTableKey, propertyKey)); + final pointer = invokeGetPointer(() => _realmLib.realm_get_backlinks(object.handle._pointer, sourceTableKey, propertyKey)); return RealmResultsHandle._(pointer, object.realm.handle); } int getListSize(RealmListHandle handle) { return using((Arena arena) { final size = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_list_size(handle._pointer, size)); + invokeGetBool(() => _realmLib.realm_list_size(handle._pointer, size)); return size.value; }); } @@ -1416,7 +1211,7 @@ class _RealmCore { Object? listGetElementAt(RealmList list, int index) { return using((Arena arena) { final realm_value = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_list_get(list.handle._pointer, index, realm_value)); + invokeGetBool(() => _realmLib.realm_list_get(list.handle._pointer, index, realm_value)); return realm_value.toDartValue( list.realm, () => _realmLib.realm_list_get_list(list.handle._pointer, index), () => _realmLib.realm_list_get_dictionary(list.handle._pointer, index)); }); @@ -1425,7 +1220,7 @@ class _RealmCore { void listAddElementAt(RealmListHandle handle, int index, Object? value, bool insert) { using((Arena arena) { final realm_value = _toRealmValue(value, arena); - _realmLib.invokeGetBool(() => (insert ? _realmLib.realm_list_insert : _realmLib.realm_list_set)(handle._pointer, index, realm_value.ref)); + invokeGetBool(() => (insert ? _realmLib.realm_list_insert : _realmLib.realm_list_set)(handle._pointer, index, realm_value.ref)); }); } @@ -1435,25 +1230,25 @@ class _RealmCore { } RealmObjectHandle listSetEmbeddedObjectAt(Realm realm, RealmListHandle handle, int index) { - final ptr = _realmLib.invokeGetPointer(() => _realmLib.realm_list_set_embedded(handle._pointer, index)); + final ptr = invokeGetPointer(() => _realmLib.realm_list_set_embedded(handle._pointer, index)); return RealmObjectHandle._(ptr, realm.handle); } RealmObjectHandle listInsertEmbeddedObjectAt(Realm realm, RealmListHandle handle, int index) { - final ptr = _realmLib.invokeGetPointer(() => _realmLib.realm_list_insert_embedded(handle._pointer, index)); + final ptr = invokeGetPointer(() => _realmLib.realm_list_insert_embedded(handle._pointer, index)); return RealmObjectHandle._(ptr, realm.handle); } void listRemoveElementAt(RealmListHandle handle, int index) { - _realmLib.invokeGetBool(() => _realmLib.realm_list_erase(handle._pointer, index)); + invokeGetBool(() => _realmLib.realm_list_erase(handle._pointer, index)); } void listMoveElement(RealmListHandle handle, int from, int to) { - _realmLib.invokeGetBool(() => _realmLib.realm_list_move(handle._pointer, from, to)); + invokeGetBool(() => _realmLib.realm_list_move(handle._pointer, from, to)); } void listDeleteAll(RealmList list) { - _realmLib.invokeGetBool(() => _realmLib.realm_list_remove_all(list.handle._pointer)); + invokeGetBool(() => _realmLib.realm_list_remove_all(list.handle._pointer)); } int listFind(RealmList list, Object? value) { @@ -1463,7 +1258,7 @@ class _RealmCore { // TODO: how should this behave for collections final realm_value = _toRealmValue(value, arena); - _realmLib.invokeGetBool( + invokeGetBool( () => _realmLib.realm_list_find( list.handle._pointer, realm_value, @@ -1476,15 +1271,15 @@ class _RealmCore { } void resultsDeleteAll(RealmResults results) { - _realmLib.invokeGetBool(() => _realmLib.realm_results_delete_all(results.handle._pointer)); + invokeGetBool(() => _realmLib.realm_results_delete_all(results.handle._pointer)); } void listClear(RealmListHandle listHandle) { - _realmLib.invokeGetBool(() => _realmLib.realm_list_clear(listHandle._pointer)); + invokeGetBool(() => _realmLib.realm_list_clear(listHandle._pointer)); } RealmSetHandle getSetProperty(RealmObjectBase object, int propertyKey) { - final pointer = _realmLib.invokeGetPointer(() => _realmLib.realm_get_set(object.handle._pointer, propertyKey)); + final pointer = invokeGetPointer(() => _realmLib.realm_get_set(object.handle._pointer, propertyKey)); return RealmSetHandle._(pointer, object.realm.handle); } @@ -1493,7 +1288,7 @@ class _RealmCore { final realm_value = _toRealmValue(value, arena); final out_index = arena(); final out_inserted = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_set_insert(handle._pointer, realm_value.ref, out_index, out_inserted)); + invokeGetBool(() => _realmLib.realm_set_insert(handle._pointer, realm_value.ref, out_index, out_inserted)); return out_inserted.value; }); } @@ -1501,7 +1296,7 @@ class _RealmCore { Object? realmSetGetElementAt(RealmSet realmSet, int index) { return using((Arena arena) { final realm_value = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_set_get(realmSet.handle._pointer, index, realm_value)); + invokeGetBool(() => _realmLib.realm_set_get(realmSet.handle._pointer, index, realm_value)); final result = realm_value.toDartValue( realmSet.realm, () => throw RealmException('Sets cannot contain collections'), () => throw RealmException('Sets cannot contain collections')); return result; @@ -1514,7 +1309,7 @@ class _RealmCore { final realm_value = _toRealmValue(value, arena); final out_index = arena(); final out_found = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_set_find(realmSet.handle._pointer, realm_value.ref, out_index, out_found)); + invokeGetBool(() => _realmLib.realm_set_find(realmSet.handle._pointer, realm_value.ref, out_index, out_found)); return out_found.value; }); } @@ -1524,19 +1319,19 @@ class _RealmCore { // TODO: do we support sets containing mixed collections final realm_value = _toRealmValue(value, arena); final out_erased = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_set_erase(realmSet.handle._pointer, realm_value.ref, out_erased)); + invokeGetBool(() => _realmLib.realm_set_erase(realmSet.handle._pointer, realm_value.ref, out_erased)); return out_erased.value; }); } void realmSetClear(RealmSetHandle handle) { - _realmLib.invokeGetBool(() => _realmLib.realm_set_clear(handle._pointer)); + invokeGetBool(() => _realmLib.realm_set_clear(handle._pointer)); } int realmSetSize(RealmSet realmSet) { return using((Arena arena) { final out_size = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_set_size(realmSet.handle._pointer, out_size)); + invokeGetBool(() => _realmLib.realm_set_size(realmSet.handle._pointer, out_size)); return out_size.value; }); } @@ -1546,11 +1341,11 @@ class _RealmCore { } void realmSetRemoveAll(RealmSet realmSet) { - _realmLib.invokeGetBool(() => _realmLib.realm_set_remove_all(realmSet.handle._pointer)); + invokeGetBool(() => _realmLib.realm_set_remove_all(realmSet.handle._pointer)); } RealmNotificationTokenHandle subscribeSetNotifications(RealmSet realmSet, NotificationsController controller) { - final pointer = _realmLib.invokeGetPointer(() => _realmLib.realm_set_add_notification_callback( + final pointer = invokeGetPointer(() => _realmLib.realm_set_add_notification_callback( realmSet.handle._pointer, controller.toPersistentHandle(), _realmLib.addresses.realm_dart_delete_persistent_handle, @@ -1564,7 +1359,7 @@ class _RealmCore { int mapGetSize(RealmMapHandle handle) { return using((Arena arena) { final size = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_dictionary_size(handle._pointer, size)); + invokeGetBool(() => _realmLib.realm_dictionary_size(handle._pointer, size)); return size.value; }); } @@ -1573,7 +1368,7 @@ class _RealmCore { return using((Arena arena) { final keyValue = _toRealmValue(key, arena); final out_erased = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_dictionary_erase(handle._pointer, keyValue.ref, out_erased)); + invokeGetBool(() => _realmLib.realm_dictionary_erase(handle._pointer, keyValue.ref, out_erased)); return out_erased.value; }); } @@ -1583,7 +1378,7 @@ class _RealmCore { final realm_value = arena(); final key_value = _toRealmValue(key, arena); final out_found = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_dictionary_find(map.handle._pointer, key_value.ref, realm_value, out_found)); + invokeGetBool(() => _realmLib.realm_dictionary_find(map.handle._pointer, key_value.ref, realm_value, out_found)); if (out_found.value) { return realm_value.toDartValue(map.realm, () => _realmLib.realm_dictionary_get_list(map.handle._pointer, key_value.ref), () => _realmLib.realm_dictionary_get_dictionary(map.handle._pointer, key_value.ref)); @@ -1598,20 +1393,20 @@ class _RealmCore { } void mapClear(RealmMapHandle mapHandle) { - _realmLib.invokeGetBool(() => _realmLib.realm_dictionary_clear(mapHandle._pointer)); + invokeGetBool(() => _realmLib.realm_dictionary_clear(mapHandle._pointer)); } RealmResultsHandle mapGetKeys(ManagedRealmMap map) { return using((Arena arena) { final out_size = arena(); final out_keys = arena>(); - _realmLib.invokeGetBool(() => _realmLib.realm_dictionary_get_keys(map.handle._pointer, out_size, out_keys)); + invokeGetBool(() => _realmLib.realm_dictionary_get_keys(map.handle._pointer, out_size, out_keys)); return RealmResultsHandle._(out_keys.value, map.realm.handle); }); } RealmResultsHandle mapGetValues(ManagedRealmMap map) { - final result = _realmLib.invokeGetPointer(() => _realmLib.realm_dictionary_to_results(map.handle._pointer)); + final result = invokeGetPointer(() => _realmLib.realm_dictionary_to_results(map.handle._pointer)); return RealmResultsHandle._(result, map.realm.handle); } @@ -1619,7 +1414,7 @@ class _RealmCore { return using((Arena arena) { final key_value = _toRealmValue(key, arena); final out_found = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_dictionary_contains_key(map.handle._pointer, key_value.ref, out_found)); + invokeGetBool(() => _realmLib.realm_dictionary_contains_key(map.handle._pointer, key_value.ref, out_found)); return out_found.value; }); } @@ -1629,7 +1424,7 @@ class _RealmCore { // TODO: how should this behave for collections final value_value = _toRealmValue(value, arena); final out_index = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_dictionary_contains_value(map.handle._pointer, value_value.ref, out_index)); + invokeGetBool(() => _realmLib.realm_dictionary_contains_value(map.handle._pointer, value_value.ref, out_index)); return out_index.value > -1; }); } @@ -1637,7 +1432,7 @@ class _RealmCore { RealmObjectHandle mapInsertEmbeddedObject(Realm realm, RealmMapHandle handle, String key) { return using((Arena arena) { final realm_value = _toRealmValue(key, arena); - final ptr = _realmLib.invokeGetPointer(() => _realmLib.realm_dictionary_insert_embedded(handle._pointer, realm_value.ref)); + final ptr = invokeGetPointer(() => _realmLib.realm_dictionary_insert_embedded(handle._pointer, realm_value.ref)); return RealmObjectHandle._(ptr, realm.handle); }); } @@ -1646,7 +1441,7 @@ class _RealmCore { using((Arena arena) { final key_value = _toRealmValue(key, arena); final value_value = _toRealmValue(value, arena); - _realmLib.invokeGetBool(() => _realmLib.realm_dictionary_insert(handle._pointer, key_value.ref, value_value.ref, nullptr, nullptr)); + invokeGetBool(() => _realmLib.realm_dictionary_insert(handle._pointer, key_value.ref, value_value.ref, nullptr, nullptr)); }); } @@ -1659,7 +1454,7 @@ class _RealmCore { } RealmMapHandle getMapProperty(RealmObjectBase object, int propertyKey) { - final pointer = _realmLib.invokeGetPointer(() => _realmLib.realm_get_dictionary(object.handle._pointer, propertyKey)); + final pointer = invokeGetPointer(() => _realmLib.realm_get_dictionary(object.handle._pointer, propertyKey)); return RealmMapHandle._(pointer, object.realm.handle); } @@ -1682,7 +1477,7 @@ class _RealmCore { } RealmResultsHandle resultsSnapshot(RealmResults results) { - final resultsPointer = _realmLib.invokeGetPointer(() => _realmLib.realm_results_snapshot(results.handle._pointer)); + final resultsPointer = invokeGetPointer(() => _realmLib.realm_results_snapshot(results.handle._pointer)); return RealmResultsHandle._(resultsPointer, results.realm.handle); } @@ -1776,7 +1571,7 @@ class _RealmCore { } RealmNotificationTokenHandle subscribeResultsNotifications(RealmResults results, NotificationsController controller) { - final pointer = _realmLib.invokeGetPointer(() => _realmLib.realm_results_add_notification_callback( + final pointer = invokeGetPointer(() => _realmLib.realm_results_add_notification_callback( results.handle._pointer, controller.toPersistentHandle(), _realmLib.addresses.realm_dart_delete_persistent_handle, @@ -1788,7 +1583,7 @@ class _RealmCore { } RealmNotificationTokenHandle subscribeListNotifications(RealmList list, NotificationsController controller) { - final pointer = _realmLib.invokeGetPointer(() => _realmLib.realm_list_add_notification_callback( + final pointer = invokeGetPointer(() => _realmLib.realm_list_add_notification_callback( list.handle._pointer, controller.toPersistentHandle(), _realmLib.addresses.realm_dart_delete_persistent_handle, @@ -1802,7 +1597,7 @@ class _RealmCore { RealmNotificationTokenHandle subscribeObjectNotifications(RealmObjectBase object, NotificationsController controller, [List? keyPaths]) { return using((Arena arena) { final kpNative = buildAndVerifyKeyPath(object, keyPaths); - final pointer = _realmLib.invokeGetPointer(() => _realmLib.realm_object_add_notification_callback( + final pointer = invokeGetPointer(() => _realmLib.realm_object_add_notification_callback( object.handle._pointer, controller.toPersistentHandle(), _realmLib.addresses.realm_dart_delete_persistent_handle, @@ -1828,12 +1623,12 @@ class _RealmCore { keypathsNative[i] = keyPaths[i].toCharPtr(arena); } - return _realmLib.invokeGetPointer(() => _realmLib.realm_create_key_path_array(object.realm.handle._pointer, classKey, length, keypathsNative)); + return invokeGetPointer(() => _realmLib.realm_create_key_path_array(object.realm.handle._pointer, classKey, length, keypathsNative)); }); } RealmNotificationTokenHandle subscribeMapNotifications(RealmMap map, NotificationsController controller) { - final pointer = _realmLib.invokeGetPointer(() => _realmLib.realm_dictionary_add_notification_callback( + final pointer = invokeGetPointer(() => _realmLib.realm_dictionary_add_notification_callback( map.handle._pointer, controller.toPersistentHandle(), _realmLib.addresses.realm_dart_delete_persistent_handle, @@ -1964,7 +1759,7 @@ class _RealmCore { RealmAppCredentialsHandle createAppCredentialsFunction(String payload) { return using((arena) { final payloadPtr = payload.toCharPtr(arena); - final credentialsPtr = _realmLib.invokeGetPointer(() => _realmLib.realm_app_credentials_new_function(payloadPtr)); + final credentialsPtr = invokeGetPointer(() => _realmLib.realm_app_credentials_new_function(payloadPtr)); return RealmAppCredentialsHandle._(credentialsPtr); }); } @@ -2132,7 +1927,7 @@ class _RealmCore { } final httpTransportHandle = _createHttpTransport(configuration.httpClient); final appConfigHandle = _createAppConfig(configuration, httpTransportHandle); - final realmAppPtr = _realmLib.invokeGetPointer(() => _realmLib.realm_app_create_cached(appConfigHandle._pointer)); + final realmAppPtr = invokeGetPointer(() => _realmLib.realm_app_create_cached(appConfigHandle._pointer)); return AppHandle._(realmAppPtr); } @@ -2144,7 +1939,7 @@ class _RealmCore { AppHandle? getApp(String id, String? baseUrl) { return using((arena) { final out_app = arena>(); - _realmLib.invokeGetBool(() => _realmLib.realm_app_get_cached(id.toCharPtr(arena), baseUrl == null ? nullptr : baseUrl.toCharPtr(arena), out_app)); + invokeGetBool(() => _realmLib.realm_app_get_cached(id.toCharPtr(arena), baseUrl == null ? nullptr : baseUrl.toCharPtr(arena), out_app)); return out_app.value == nullptr ? null : AppHandle._(out_app.value); }); } @@ -2191,7 +1986,7 @@ class _RealmCore { final completer = Completer(); final userdata = _createAsyncUserCallbackUserdata(completer); - _realmLib.invokeGetBool( + invokeGetBool( () => _realmLib.realm_app_log_in_with_credentials( app.handle._pointer, credentials.handle._pointer, @@ -2218,7 +2013,7 @@ class _RealmCore { Future appEmailPasswordRegisterUser(App app, String email, String password) { final completer = Completer(); using((arena) { - _realmLib.invokeGetBool(() => _realmLib.realm_app_email_password_provider_client_register_email( + invokeGetBool(() => _realmLib.realm_app_email_password_provider_client_register_email( app.handle._pointer, email.toCharPtr(arena), password.toRealmString(arena).ref, @@ -2233,7 +2028,7 @@ class _RealmCore { Future emailPasswordConfirmUser(App app, String token, String tokenId) async { final completer = Completer(); using((arena) { - _realmLib.invokeGetBool(() => _realmLib.realm_app_email_password_provider_client_confirm_user( + invokeGetBool(() => _realmLib.realm_app_email_password_provider_client_confirm_user( app.handle._pointer, token.toCharPtr(arena), tokenId.toCharPtr(arena), @@ -2248,7 +2043,7 @@ class _RealmCore { Future emailPasswordResendUserConfirmation(App app, String email) { final completer = Completer(); using((arena) { - _realmLib.invokeGetBool(() => _realmLib.realm_app_email_password_provider_client_resend_confirmation_email( + invokeGetBool(() => _realmLib.realm_app_email_password_provider_client_resend_confirmation_email( app.handle._pointer, email.toCharPtr(arena), _realmLib.addresses.realm_dart_void_completion_callback, @@ -2262,7 +2057,7 @@ class _RealmCore { Future emailPasswordCompleteResetPassword(App app, String password, String token, String tokenId) { final completer = Completer(); using((arena) { - _realmLib.invokeGetBool(() => _realmLib.realm_app_email_password_provider_client_reset_password( + invokeGetBool(() => _realmLib.realm_app_email_password_provider_client_reset_password( app.handle._pointer, password.toRealmString(arena).ref, token.toCharPtr(arena), @@ -2278,7 +2073,7 @@ class _RealmCore { Future emailPasswordResetPassword(App app, String email) { final completer = Completer(); using((arena) { - _realmLib.invokeGetBool(() => _realmLib.realm_app_email_password_provider_client_send_reset_password_email( + invokeGetBool(() => _realmLib.realm_app_email_password_provider_client_send_reset_password_email( app.handle._pointer, email.toCharPtr(arena), _realmLib.addresses.realm_dart_void_completion_callback, @@ -2292,7 +2087,7 @@ class _RealmCore { Future emailPasswordCallResetPasswordFunction(App app, String email, String password, String? argsAsJSON) { final completer = Completer(); using((arena) { - _realmLib.invokeGetBool(() => _realmLib.realm_app_email_password_provider_client_call_reset_password_function( + invokeGetBool(() => _realmLib.realm_app_email_password_provider_client_call_reset_password_function( app.handle._pointer, email.toCharPtr(arena), password.toRealmString(arena).ref, @@ -2308,7 +2103,7 @@ class _RealmCore { Future emailPasswordRetryCustomConfirmationFunction(App app, String email) { final completer = Completer(); using((arena) { - _realmLib.invokeGetBool(() => _realmLib.realm_app_email_password_provider_client_retry_custom_confirmation( + invokeGetBool(() => _realmLib.realm_app_email_password_provider_client_retry_custom_confirmation( app.handle._pointer, email.toCharPtr(arena), _realmLib.addresses.realm_dart_void_completion_callback, @@ -2330,7 +2125,7 @@ class _RealmCore { Future logOut(App application, User? user) { final completer = Completer(); if (user == null) { - _realmLib.invokeGetBool( + invokeGetBool( () => _realmLib.realm_app_log_out_current_user( application.handle._pointer, _realmLib.addresses.realm_dart_void_completion_callback, @@ -2339,7 +2134,7 @@ class _RealmCore { ), "Logout failed"); } else { - _realmLib.invokeGetBool( + invokeGetBool( () => _realmLib.realm_app_log_out( application.handle._pointer, user.handle._pointer, @@ -2365,7 +2160,7 @@ class _RealmCore { List _getUsers(App app, Arena arena, {int expectedSize = 2}) { final actualCount = arena(); final usersPtr = arena>(expectedSize); - _realmLib.invokeGetBool(() => _realmLib.realm_app_get_all_users(app.handle._pointer, usersPtr, expectedSize, actualCount)); + invokeGetBool(() => _realmLib.realm_app_get_all_users(app.handle._pointer, usersPtr, expectedSize, actualCount)); if (expectedSize < actualCount.value) { // The supplied array was too small - resize it @@ -2383,7 +2178,7 @@ class _RealmCore { Future removeUser(App app, User user) { final completer = Completer(); - _realmLib.invokeGetBool( + invokeGetBool( () => _realmLib.realm_app_remove_user( app.handle._pointer, user.handle._pointer, @@ -2397,7 +2192,7 @@ class _RealmCore { void switchUser(App application, User user) { return using((arena) { - _realmLib.invokeGetBool( + invokeGetBool( () => _realmLib.realm_app_switch_user( application.handle._pointer, user.handle._pointer, @@ -2420,7 +2215,7 @@ class _RealmCore { Future updateBaseUrl(App app, Uri? baseUrl) { final completer = Completer(); using((arena) { - _realmLib.invokeGetBool( + invokeGetBool( () => _realmLib.realm_app_update_base_url( app.handle._pointer, baseUrl?.toString().toCharPtr(arena) ?? nullptr, @@ -2440,7 +2235,7 @@ class _RealmCore { Future userRefreshCustomData(App app, User user) { final completer = Completer(); - _realmLib.invokeGetBool( + invokeGetBool( () => _realmLib.realm_app_refresh_custom_data( app.handle._pointer, user.handle._pointer, @@ -2454,7 +2249,7 @@ class _RealmCore { Future userLinkCredentials(App app, User user, Credentials credentials) { final completer = Completer(); - _realmLib.invokeGetBool( + invokeGetBool( () => _realmLib.realm_app_link_user( app.handle._pointer, user.handle._pointer, @@ -2473,7 +2268,7 @@ class _RealmCore { } String userGetId(User user) { - final idPtr = _realmLib.invokeGetPointer(() => _realmLib.realm_user_get_identity(user.handle._pointer), "Error while getting user id"); + final idPtr = invokeGetPointer(() => _realmLib.realm_user_get_identity(user.handle._pointer), "Error while getting user id"); final userId = idPtr.cast().toDartString(); return userId; } @@ -2496,7 +2291,7 @@ class _RealmCore { List _userGetIdentities(User user, Arena arena, {int expectedSize = 2}) { final actualCount = arena(); final identitiesPtr = arena(expectedSize); - _realmLib.invokeGetBool(() => _realmLib.realm_user_get_all_identities(user.handle._pointer, identitiesPtr, expectedSize, actualCount)); + invokeGetBool(() => _realmLib.realm_user_get_all_identities(user.handle._pointer, identitiesPtr, expectedSize, actualCount)); if (expectedSize < actualCount.value) { // The supplied array was too small - resize it @@ -2516,12 +2311,12 @@ class _RealmCore { } Future userLogOut(User user) { - _realmLib.invokeGetBool(() => _realmLib.realm_user_log_out(user.handle._pointer), "Logout failed"); + invokeGetBool(() => _realmLib.realm_user_log_out(user.handle._pointer), "Logout failed"); return Future.value(); } String? userGetDeviceId(User user) { - final deviceId = _realmLib.invokeGetPointer(() => _realmLib.realm_user_get_device_id(user.handle._pointer)); + final deviceId = invokeGetPointer(() => _realmLib.realm_user_get_device_id(user.handle._pointer)); return deviceId.cast().toRealmDartString(treatEmptyAsNull: true, freeRealmMemory: true); } @@ -2531,23 +2326,23 @@ class _RealmCore { } UserProfile userGetProfileData(User user) { - final data = _realmLib.invokeGetPointer(() => _realmLib.realm_user_get_profile_data(user.handle._pointer)); + final data = invokeGetPointer(() => _realmLib.realm_user_get_profile_data(user.handle._pointer)); final dynamic profileData = jsonDecode(data.cast().toRealmDartString(freeRealmMemory: true)!); return UserProfile(profileData as Map); } String userGetRefreshToken(User user) { - final token = _realmLib.invokeGetPointer(() => _realmLib.realm_user_get_refresh_token(user.handle._pointer)); + final token = invokeGetPointer(() => _realmLib.realm_user_get_refresh_token(user.handle._pointer)); return token.cast().toRealmDartString(freeRealmMemory: true)!; } String userGetAccessToken(User user) { - final token = _realmLib.invokeGetPointer(() => _realmLib.realm_user_get_access_token(user.handle._pointer)); + final token = invokeGetPointer(() => _realmLib.realm_user_get_access_token(user.handle._pointer)); return token.cast().toRealmDartString(freeRealmMemory: true)!; } SessionHandle realmGetSession(Realm realm) { - return SessionHandle._(_realmLib.invokeGetPointer(() => _realmLib.realm_sync_session_get(realm.handle._pointer)), realm.handle); + return SessionHandle._(invokeGetPointer(() => _realmLib.realm_sync_session_get(realm.handle._pointer)), realm.handle); } String sessionGetPath(Session session) { @@ -2595,7 +2390,7 @@ class _RealmCore { final isStreaming = mode == ProgressMode.reportIndefinitely; final callback = Pointer.fromFunction(_syncProgressCallback); final userdata = _realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle._pointer); - final tokenPtr = _realmLib.invokeGetPointer(() => _realmLib.realm_sync_session_register_progress_notifier( + final tokenPtr = invokeGetPointer(() => _realmLib.realm_sync_session_register_progress_notifier( session.handle._pointer, _realmLib.addresses.realm_dart_sync_progress_callback, direction.index, @@ -2658,7 +2453,7 @@ class _RealmCore { } if (errorCode != nullptr) { // Throw RealmException instead of RealmError to be recoverable by the user. - completer.completeError(RealmException(errorCode.toSyncError().toString())); + completer.completeError(RealmException(errorCode.toDart().toString())); } else { completer.complete(); } @@ -2720,13 +2515,7 @@ class _RealmCore { } if (Platform.isLinux) { - String appSupportDir = PlatformEx.fromEnvironment( - "XDG_DATA_HOME", - defaultValue: PlatformEx.fromEnvironment( - "HOME", - defaultValue: Directory.current.absolute.path, - ), - ); + final appSupportDir = Platform.environment['XDG_DATA_HOME'] ?? Platform.environment['HOME'] ?? Directory.current.absolute.path; return path.join(appSupportDir, ".local/share", _getAppDirectoryFromPlugin()); } @@ -2746,7 +2535,7 @@ class _RealmCore { Future deleteUser(App app, User user) { final completer = Completer(); - _realmLib.invokeGetBool( + invokeGetBool( () => _realmLib.realm_app_delete_user( app.handle._pointer, user.handle._pointer, @@ -2763,19 +2552,19 @@ class _RealmCore { } RealmHandle freeze(Realm realm) { - final ptr = _realmLib.invokeGetPointer(() => _realmLib.realm_freeze(realm.handle._pointer)); + final ptr = invokeGetPointer(() => _realmLib.realm_freeze(realm.handle._pointer)); return RealmHandle._(ptr); } RealmResultsHandle resolveResults(RealmResults realmResults, Realm frozenRealm) { - final ptr = _realmLib.invokeGetPointer(() => _realmLib.realm_results_resolve_in(realmResults.handle._pointer, frozenRealm.handle._pointer)); + final ptr = invokeGetPointer(() => _realmLib.realm_results_resolve_in(realmResults.handle._pointer, frozenRealm.handle._pointer)); return RealmResultsHandle._(ptr, frozenRealm.handle); } RealmObjectHandle? resolveObject(RealmObjectBase object, Realm frozenRealm) { return using((Arena arena) { final resultPtr = arena>(); - _realmLib.invokeGetBool(() => _realmLib.realm_object_resolve_in(object.handle._pointer, frozenRealm.handle._pointer, resultPtr)); + invokeGetBool(() => _realmLib.realm_object_resolve_in(object.handle._pointer, frozenRealm.handle._pointer, resultPtr)); return resultPtr == nullptr ? null : RealmObjectHandle._(resultPtr.value, frozenRealm.handle); }); } @@ -2783,7 +2572,7 @@ class _RealmCore { RealmListHandle? resolveList(ManagedRealmList list, Realm frozenRealm) { return using((Arena arena) { final resultPtr = arena>(); - _realmLib.invokeGetBool(() => _realmLib.realm_list_resolve_in(list.handle._pointer, frozenRealm.handle._pointer, resultPtr)); + invokeGetBool(() => _realmLib.realm_list_resolve_in(list.handle._pointer, frozenRealm.handle._pointer, resultPtr)); return resultPtr == nullptr ? null : RealmListHandle._(resultPtr.value, frozenRealm.handle); }); } @@ -2791,7 +2580,7 @@ class _RealmCore { RealmSetHandle? resolveSet(ManagedRealmSet set, Realm frozenRealm) { return using((Arena arena) { final resultPtr = arena>(); - _realmLib.invokeGetBool(() => _realmLib.realm_set_resolve_in(set.handle._pointer, frozenRealm.handle._pointer, resultPtr)); + invokeGetBool(() => _realmLib.realm_set_resolve_in(set.handle._pointer, frozenRealm.handle._pointer, resultPtr)); return resultPtr == nullptr ? null : RealmSetHandle._(resultPtr.value, frozenRealm.handle); }); } @@ -2799,7 +2588,7 @@ class _RealmCore { RealmMapHandle? resolveMap(ManagedRealmMap map, Realm frozenRealm) { return using((Arena arena) { final resultPtr = arena>(); - _realmLib.invokeGetBool(() => _realmLib.realm_dictionary_resolve_in(map.handle._pointer, frozenRealm.handle._pointer, resultPtr)); + invokeGetBool(() => _realmLib.realm_dictionary_resolve_in(map.handle._pointer, frozenRealm.handle._pointer, resultPtr)); return resultPtr == nullptr ? null : RealmMapHandle._(resultPtr.value, frozenRealm.handle); }); } @@ -2833,7 +2622,7 @@ class _RealmCore { return using((Arena arena) { final namePtr = name.toCharPtr(arena); final completer = Completer(); - _realmLib.invokeGetBool(() => _realmLib.realm_app_user_apikey_provider_client_create_apikey( + invokeGetBool(() => _realmLib.realm_app_user_apikey_provider_client_create_apikey( user.app.handle._pointer, user.handle._pointer, namePtr, @@ -2850,7 +2639,7 @@ class _RealmCore { return using((Arena arena) { final completer = Completer(); final native_id = id.toNative(arena); - _realmLib.invokeGetBool(() => _realmLib.realm_app_user_apikey_provider_client_fetch_apikey( + invokeGetBool(() => _realmLib.realm_app_user_apikey_provider_client_fetch_apikey( user.app.handle._pointer, user.handle._pointer, native_id.ref, @@ -2866,7 +2655,7 @@ class _RealmCore { Future> fetchAllApiKeys(User user) { return using((Arena arena) { final completer = Completer>(); - _realmLib.invokeGetBool(() => _realmLib.realm_app_user_apikey_provider_client_fetch_apikeys( + invokeGetBool(() => _realmLib.realm_app_user_apikey_provider_client_fetch_apikeys( user.app.handle._pointer, user.handle._pointer, _realmLib.addresses.realm_dart_apikey_list_callback, @@ -2882,7 +2671,7 @@ class _RealmCore { return using((Arena arena) { final completer = Completer(); final native_id = id.toNative(arena); - _realmLib.invokeGetBool(() => _realmLib.realm_app_user_apikey_provider_client_delete_apikey( + invokeGetBool(() => _realmLib.realm_app_user_apikey_provider_client_delete_apikey( user.app.handle._pointer, user.handle._pointer, native_id.ref, @@ -2951,7 +2740,7 @@ class _RealmCore { final completer = Completer(); final native_id = objectId.toNative(arena); - _realmLib.invokeGetBool(() => _realmLib.realm_app_user_apikey_provider_client_disable_apikey( + invokeGetBool(() => _realmLib.realm_app_user_apikey_provider_client_disable_apikey( user.app.handle._pointer, user.handle._pointer, native_id.ref, @@ -2968,7 +2757,7 @@ class _RealmCore { return using((Arena arena) { final completer = Completer(); final native_id = objectId.toNative(arena); - _realmLib.invokeGetBool(() => _realmLib.realm_app_user_apikey_provider_client_enable_apikey( + invokeGetBool(() => _realmLib.realm_app_user_apikey_provider_client_enable_apikey( user.app.handle._pointer, user.handle._pointer, native_id.ref, @@ -3013,7 +2802,7 @@ class _RealmCore { Future callAppFunction(App app, User user, String functionName, String? argsAsJSON) { return using((arena) { final completer = Completer(); - _realmLib.invokeGetBool(() => _realmLib.realm_app_call_function( + invokeGetBool(() => _realmLib.realm_app_call_function( app.handle._pointer, user.handle._pointer, functionName.toCharPtr(arena), @@ -3030,7 +2819,7 @@ class _RealmCore { bool compact(Realm realm) { return using((arena) { final out_did_compact = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_compact(realm.handle._pointer, out_did_compact)); + invokeGetBool(() => _realmLib.realm_compact(realm.handle._pointer, out_did_compact)); return out_did_compact.value; }); } @@ -3038,7 +2827,7 @@ class _RealmCore { bool immediatelyRunFileActions(App app, String realmPath) { return using((arena) { final out_did_run = arena(); - _realmLib.invokeGetBool(() => _realmLib.realm_sync_immediately_run_file_actions(app.handle._pointer, realmPath.toCharPtr(arena), out_did_run), + invokeGetBool(() => _realmLib.realm_sync_immediately_run_file_actions(app.handle._pointer, realmPath.toCharPtr(arena), out_did_run), "An error occurred while resetting the Realm. Check if the file is in use: '$realmPath'"); return out_did_run.value; }); @@ -3046,7 +2835,7 @@ class _RealmCore { void writeCopy(Realm realm, Configuration config) { final configHandle = _createConfig(config); - _realmLib.invokeGetBool(() => _realmLib.realm_convert_with_config(realm.handle._pointer, configHandle._pointer, false)); + invokeGetBool(() => _realmLib.realm_convert_with_config(realm.handle._pointer, configHandle._pointer, false)); } void _createCollection(Realm realm, RealmValue value, Pointer Function() createList, Pointer Function() createMap) { @@ -3054,7 +2843,7 @@ class _RealmCore { try { switch (value.collectionType) { case RealmCollectionType.list: - final listPointer = _realmLib.invokeGetPointer(createList); + final listPointer = invokeGetPointer(createList); final listHandle = RealmListHandle._(listPointer, realm.handle); collectionHandle = listHandle; @@ -3067,7 +2856,7 @@ class _RealmCore { list.add(item); } case RealmCollectionType.map: - final mapPointer = _realmLib.invokeGetPointer(createMap); + final mapPointer = invokeGetPointer(createMap); final mapHandle = RealmMapHandle._(mapPointer, realm.handle); collectionHandle = mapHandle; @@ -3103,17 +2892,6 @@ class _RealmCore { } } -class LastError { - final int code; - final String? message; - final Object? userError; - - LastError(this.code, [this.message, this.userError]); - - @override - String toString() => "${message ?? 'No message'}. Error code: $code."; -} - // Flag to enable trace on finalization. // // Be aware that the trace is likely late, and it might in rare case be missing, @@ -3279,6 +3057,38 @@ class SchedulerHandle extends HandleBase { class RealmObjectHandle extends RootedHandleBase { RealmObjectHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 112); + + factory RealmObjectHandle.createWithPrimaryKey(RealmHandle realm, int classKey, Object? primaryKey) { + return using((Arena arena) { + final realm_value = _toRealmValue(primaryKey, arena); + final realmPtr = invokeGetPointer(() => _realmLib.realm_object_create_with_primary_key(realm._pointer, classKey, realm_value.ref)); + return RealmObjectHandle._(realmPtr, realm); + }); + } + + factory RealmObjectHandle.create(RealmHandle realm, int classKey) { + final realmPtr = invokeGetPointer(() => _realmLib.realm_object_create(realm._pointer, classKey)); + return RealmObjectHandle._(realmPtr, realm); + } + + factory RealmObjectHandle.createEmbedded(RealmObjectHandle parent, int propertyKey) { + final objectPtr = invokeGetPointer(() => _realmLib.realm_set_embedded(parent._pointer, propertyKey)); + return RealmObjectHandle._(objectPtr, parent._root); + } + + factory RealmObjectHandle.getOrCreateWithPrimaryKey(RealmHandle realm, int classKey, Object? primaryKey) { + return using((Arena arena) { + final realm_value = _toRealmValue(primaryKey, arena); + final didCreate = arena(); + final realmPtr = invokeGetPointer(() => _realmLib.realm_object_get_or_create_with_primary_key( + realm._pointer, + classKey, + realm_value.ref, + didCreate, + )); + return RealmObjectHandle._(realmPtr, realm); + }); + } } class _RealmLinkHandle { @@ -3361,10 +3171,6 @@ class UserHandle extends HandleBase { UserHandle._(Pointer pointer) : super(pointer, 24); } -class SubscriptionHandle extends HandleBase { - SubscriptionHandle._(Pointer pointer) : super(pointer, 184); -} - class RealmAsyncOpenTaskHandle extends HandleBase { RealmAsyncOpenTaskHandle._(Pointer pointer) : super(pointer, 32); } @@ -3373,18 +3179,7 @@ class RealmAsyncOpenTaskProgressNotificationTokenHandle extends HandleBase pointer) : super(pointer, 40); } -class SubscriptionSetHandle extends RootedHandleBase { - @override - bool get shouldRoot => true; - - SubscriptionSetHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 128); -} - -class MutableSubscriptionSetHandle extends SubscriptionSetHandle { - MutableSubscriptionSetHandle._(Pointer pointer, RealmHandle root) : super._(pointer.cast(), root); - Pointer get _mutablePointer => super._pointer.cast(); -} class SessionHandle extends RootedHandleBase { @override @@ -3423,23 +3218,6 @@ extension _StringEx on String { } } -extension _RealmLibraryEx on RealmLibrary { - void invokeGetBool(bool Function() callback, [String? errorMessage]) { - bool success = callback(); - if (!success) { - realmCore.throwLastError(errorMessage); - } - } - - Pointer invokeGetPointer(Pointer Function() callback, [String? errorMessage]) { - final result = callback(); - if (result == nullptr) { - realmCore.throwLastError(errorMessage); - } - return result; - } -} - Pointer _toRealmValue(Object? value, Allocator allocator) { final realm_value = allocator(); if (value is RealmValue && value.type.isCollection) { @@ -3605,7 +3383,7 @@ extension on realm_value_t { throw RealmException('toDartValue called with a list argument but without a list getter'); } - final listPointer = _realmLib.invokeGetPointer(() => getList()); + final listPointer = invokeGetPointer(() => getList()); final listHandle = RealmListHandle._(listPointer, realm.handle); return realm.createList(listHandle, null); case realm_value_type.RLM_TYPE_DICTIONARY: @@ -3613,7 +3391,7 @@ extension on realm_value_t { throw RealmException('toDartValue called with a list argument but without a list getter'); } - final mapPointer = _realmLib.invokeGetPointer(() => getMap()); + final mapPointer = invokeGetPointer(() => getMap()); final mapHandle = RealmMapHandle._(mapPointer, realm.handle); return realm.createMap(mapHandle, null); default: @@ -3697,9 +3475,9 @@ extension on Pointer { } extension on realm_sync_error { - SyncErrorDetails toSyncErrorDetails() { + SyncErrorDetails toDart() { final message = status.message.cast().toRealmDartString()!; - final userInfoMap = user_info_map.toMap(user_info_length); + final userInfoMap = user_info_map.toDart(user_info_length); final originalFilePathKey = c_original_file_path_key.cast().toRealmDartString(); final recoveryFilePathKey = c_recovery_file_path_key.cast().toRealmDartString(); @@ -3717,7 +3495,7 @@ extension on realm_sync_error { } extension on Pointer { - Map? toMap(int length) { + Map? toDart(int length) { if (this == nullptr) { return null; } @@ -3750,7 +3528,7 @@ extension on Pointer { } extension on Pointer { - SyncError toSyncError() { + SyncError toDart() { final message = ref.message.cast().toDartString(); final details = SyncErrorDetails(message, ref.error, ref.user_code_error.toUserCodeError()); return SyncErrorInternal.createSyncError(details); @@ -3885,13 +3663,6 @@ class SyncErrorDetails { }); } -extension on realm_error { - LastError toLastError() { - final message = this.message.cast().toRealmDartString(); - return LastError(error, message, user_code_error.toUserCodeError()); - } -} - extension on RealmValueType { String toQueryArgString() { return switch (this) { diff --git a/packages/realm_dart/lib/src/native/subscription_handle.dart b/packages/realm_dart/lib/src/native/subscription_handle.dart new file mode 100644 index 000000000..3b1fad6f4 --- /dev/null +++ b/packages/realm_dart/lib/src/native/subscription_handle.dart @@ -0,0 +1,22 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + +part of 'realm_core.dart'; + +class SubscriptionHandle extends HandleBase { + SubscriptionHandle._(Pointer pointer) : super(pointer, 184); + + ObjectId get id => _realmLib.realm_sync_subscription_id(_pointer).toDart(); + + String? get name => _realmLib.realm_sync_subscription_name(_pointer).toDart(); + + String get objectClassName => _realmLib.realm_sync_subscription_object_class_name(_pointer).toDart()!; + + String get queryString => _realmLib.realm_sync_subscription_query_string(_pointer).toDart()!; + + DateTime get createdAt => _realmLib.realm_sync_subscription_created_at(_pointer).toDart(); + + DateTime get updatedAt => _realmLib.realm_sync_subscription_updated_at(_pointer).toDart(); + + bool equalTo(SubscriptionHandle other) => _realmLib.realm_equals(_pointer.cast(), other._pointer.cast()); +} diff --git a/packages/realm_dart/lib/src/native/subscription_set_handle.dart b/packages/realm_dart/lib/src/native/subscription_set_handle.dart new file mode 100644 index 000000000..017eae39c --- /dev/null +++ b/packages/realm_dart/lib/src/native/subscription_set_handle.dart @@ -0,0 +1,66 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + +part of 'realm_core.dart'; + +class SubscriptionSetHandle extends RootedHandleBase { + @override + bool get shouldRoot => true; + + SubscriptionSetHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 128); + + void refresh() => invokeGetBool(() => _realmLib.realm_sync_subscription_set_refresh(_pointer)); + + int get size => _realmLib.realm_sync_subscription_set_size(_pointer); + + Exception? get error { + final error = _realmLib.realm_sync_subscription_set_error_str(_pointer); + final message = error.cast().toRealmDartString(treatEmptyAsNull: true); + return message == null ? null : RealmException(message); + } + + SubscriptionHandle operator [](int index) => SubscriptionHandle._(invokeGetPointer(() => _realmLib.realm_sync_subscription_at(_pointer, index))); + + SubscriptionHandle? findByName(String name) { + return using((arena) { + final result = _realmLib.realm_sync_find_subscription_by_name( + _pointer, + name.toCharPtr(arena), + ); + return result == nullptr ? null : SubscriptionHandle._(result); + }); + } + + SubscriptionHandle? findByResults(RealmResults results) { + final result = _realmLib.realm_sync_find_subscription_by_results( + _pointer, + results.handle._pointer, + ); + return result == nullptr ? null : SubscriptionHandle._(result); + } + + int get version => _realmLib.realm_sync_subscription_set_version(_pointer); + + SubscriptionSetState get state => SubscriptionSetState.values[_realmLib.realm_sync_subscription_set_state(_pointer)]; + + MutableSubscriptionSetHandle toMutable() => + MutableSubscriptionSetHandle._(invokeGetPointer(() => _realmLib.realm_sync_make_subscription_set_mutable(_pointer)), _root); + + static void _stateChangeCallback(Object userdata, int state) { + final completer = userdata as CancellableCompleter; + if (!completer.isCancelled) { + completer.complete(SubscriptionSetState.values[state]); + } + } + + Future waitForStateChange(SubscriptionSetState notifyWhen, [CancellationToken? cancellationToken]) { + final completer = CancellableCompleter(cancellationToken); + if (!completer.isCancelled) { + final callback = Pointer.fromFunction(_stateChangeCallback); + final userdata = _realmLib.realm_dart_userdata_async_new(completer, callback.cast(), scheduler.handle._pointer); + _realmLib.realm_sync_on_subscription_set_state_change_async(_pointer, notifyWhen.index, + _realmLib.addresses.realm_dart_sync_on_subscription_state_changed_callback, userdata.cast(), _realmLib.addresses.realm_dart_userdata_async_free); + } + return completer.future; + } +} diff --git a/packages/realm_dart/lib/src/realm_class.dart b/packages/realm_dart/lib/src/realm_class.dart index 79427fe08..12e53b51d 100644 --- a/packages/realm_dart/lib/src/realm_class.dart +++ b/packages/realm_dart/lib/src/realm_class.dart @@ -477,7 +477,7 @@ class Realm implements Finalizable { if (result == null || result.handle.released) { result = SubscriptionSetInternal.create(this, realmCore.getSubscriptions(this)); - realmCore.refreshSubscriptionSet(result); + result.handle.refresh(); _subscriptions = WeakReference(result); } diff --git a/packages/realm_dart/lib/src/subscription.dart b/packages/realm_dart/lib/src/subscription.dart index 48dd9f0ec..5932c3b06 100644 --- a/packages/realm_dart/lib/src/subscription.dart +++ b/packages/realm_dart/lib/src/subscription.dart @@ -12,40 +12,40 @@ import 'realm_class.dart'; /// evaluate the query that the app subscribed to and will send data /// that matches it as well as remove data that no longer does. /// {@category Sync} -class Subscription implements Finalizable { +final class Subscription implements Finalizable { final SubscriptionHandle _handle; Subscription._(this._handle); - late final ObjectId _id = realmCore.subscriptionId(this); + late final ObjectId _id = _handle.id; /// Name of the [Subscription], if one was provided at creation time. - String? get name => realmCore.subscriptionName(this); + String? get name => _handle.name; /// Class name of objects the [Subscription] refers to. /// /// If your types are remapped using [MapTo], the value /// returned will be the mapped-to value - i.e. the one that Realm uses internally /// rather than the name of the generated Dart class. - String get objectClassName => realmCore.subscriptionObjectClassName(this); + String get objectClassName => _handle.objectClassName; /// Query string that describes the [Subscription]. /// /// Objects matched by the query will be sent to the device by the server. - String get queryString => realmCore.subscriptionQueryString(this); + String get queryString => _handle.queryString; /// Timestamp when this [Subscription] was created. - DateTime get createdAt => realmCore.subscriptionCreatedAt(this); + DateTime get createdAt => _handle.createdAt; /// Timestamp when this [Subscription] was last updated. - DateTime get updatedAt => realmCore.subscriptionUpdatedAt(this); + DateTime get updatedAt => _handle.updatedAt; @override // ignore: hash_and_equals bool operator ==(Object other) { if (identical(this, other)) return true; if (other is! Subscription) return false; - return realmCore.subscriptionEquals(this, other); + return _handle.equalTo(other._handle); } } @@ -59,7 +59,7 @@ extension SubscriptionInternal on Subscription { ObjectId get id => _id; } -class _SubscriptionIterator implements Iterator { +final class _SubscriptionIterator implements Iterator { int _index = -1; final SubscriptionSet _subscriptions; @@ -112,7 +112,7 @@ enum SubscriptionSetState { /// Realm is an expensive operation server-side, even if there's very little data that needs /// downloading. /// {@category Sync} -abstract class SubscriptionSet with IterableMixin implements Finalizable { +sealed class SubscriptionSet with IterableMixin implements Finalizable { final Realm _realm; SubscriptionSetHandle _handle; @@ -121,20 +121,14 @@ abstract class SubscriptionSet with IterableMixin implements Final /// Finds an existing [Subscription] in this set by its query /// /// The [query] is represented by the corresponding [RealmResults] object. - Subscription? find(RealmResults query) { - final result = realmCore.findSubscriptionByResults(this, query); - return result == null ? null : Subscription._(result); - } + Subscription? find(RealmResults query) => _handle.findByResults(query).convert(Subscription._); /// Finds an existing [Subscription] in this set by name. - Subscription? findByName(String name) { - final result = realmCore.findSubscriptionByName(this, name); - return result == null ? null : Subscription._(result); - } + Subscription? findByName(String name) => _handle.findByName(name).convert(Subscription._); Future _waitForStateChange(SubscriptionSetState state, [CancellationToken? cancellationToken]) async { - final result = await realmCore.waitForSubscriptionSetStateChange(this, state, cancellationToken); - realmCore.refreshSubscriptionSet(this); + final result = await _handle.waitForStateChange(state, cancellationToken); + _handle.refresh(); return result; } @@ -153,15 +147,15 @@ abstract class SubscriptionSet with IterableMixin implements Final } /// Returns the error if the subscription set is in the [SubscriptionSetState.error] state. - Exception? get error => realmCore.getSubscriptionSetError(this); + Exception? get error => _handle.error; @override - int get length => realmCore.getSubscriptionSetSize(this); + int get length => _handle.size; @override Subscription elementAt(int index) { RangeError.checkValidRange(index, null, length); - return Subscription._(realmCore.subscriptionAt(this, index)); + return Subscription._(_handle[index]); } /// Gets the [Subscription] at the specified index in the set. @@ -180,11 +174,11 @@ abstract class SubscriptionSet with IterableMixin implements Final void update(void Function(MutableSubscriptionSet mutableSubscriptions) action); /// Gets the version of the subscription set. - int get version => realmCore.subscriptionSetGetVersion(this); + int get version => _handle.version; /// Gets the state of the subscription set. SubscriptionSetState get state { - final state = realmCore.subscriptionSetGetState(this); + final state = _handle.state; switch (state) { case SubscriptionSetState._uncommitted: case SubscriptionSetState._bootstrapping: @@ -202,28 +196,19 @@ extension SubscriptionSetInternal on SubscriptionSet { _handle.keepAlive(); } - Realm get realm => _realm; - SubscriptionSetHandle get handle { - if (_handle.released) { - throw RealmClosedError('Cannot access a SubscriptionSet that belongs to a closed Realm'); - } - - return _handle; - } - static SubscriptionSet create(Realm realm, SubscriptionSetHandle handle) => ImmutableSubscriptionSet._(realm, handle); } -class ImmutableSubscriptionSet extends SubscriptionSet { +final class ImmutableSubscriptionSet extends SubscriptionSet { ImmutableSubscriptionSet._(super.realm, super.handle) : super._(); @override void update(void Function(MutableSubscriptionSet mutableSubscriptions) action) { - final mutableSubscriptions = MutableSubscriptionSet._(realm, realmCore.subscriptionSetMakeMutable(this)); + final mutableSubscriptions = MutableSubscriptionSet._(_realm, _handle.toMutable()); final oldHandle = _handle; try { action(mutableSubscriptions); - _handle = realmCore.subscriptionSetCommit(mutableSubscriptions); + __handle = mutableSubscriptions._handle.commit(); } finally { // Release as early as possible, as we cannot start new update, until this is released! mutableSubscriptions._handle.release(); @@ -234,10 +219,11 @@ class ImmutableSubscriptionSet extends SubscriptionSet { /// A mutable view to a [SubscriptionSet]. Obtained by calling [SubscriptionSet.update]. /// {@category Sync} -class MutableSubscriptionSet extends SubscriptionSet { - final MutableSubscriptionSetHandle _handle; +final class MutableSubscriptionSet extends SubscriptionSet { + @override + MutableSubscriptionSetHandle get _handle => super._handle as MutableSubscriptionSetHandle; - MutableSubscriptionSet._(Realm realm, this._handle) : super._(realm, _handle); + MutableSubscriptionSet._(Realm realm, MutableSubscriptionSetHandle handle) : super._(realm, handle); @override void update(void Function(MutableSubscriptionSet mutableSubscriptions) action) { @@ -254,28 +240,21 @@ class MutableSubscriptionSet extends SubscriptionSet { /// If [update] is specified to `true`, then any existing query will be replaced. /// Otherwise a [RealmException] is thrown, in case of duplicates. /// {@category Sync} - Subscription add(RealmResults query, {String? name, bool update = false}) { - return Subscription._(realmCore.insertOrAssignSubscription(this, query, name, update)); - } + Subscription add(RealmResults query, {String? name, bool update = false}) => + Subscription._(_handle.insertOrAssignSubscription(query, name, update)); /// Removes the [subscription] from the set, if it exists. - bool remove(Subscription subscription) { - return realmCore.eraseSubscriptionById(this, subscription); - } + bool remove(Subscription subscription) => _handle.erase(subscription); /// Removes the [query] from the set, if it exists. - bool removeByQuery(RealmResults query) { - return realmCore.eraseSubscriptionByResults(this, query); - } + bool removeByQuery(RealmResults query) => _handle.eraseByResults(query); /// Removes the subscription from the set that matches by [name], if it exists. - bool removeByName(String name) { - return realmCore.eraseSubscriptionByName(this, name); - } + bool removeByName(String name) => _handle.eraseByName(name); /// Removes the subscriptions from the set that matches by type, if it exists. bool removeByType() { - final name = realm.schema.singleWhere((e) => e.type == T).name; + final name = _realm.schema.singleWhere((e) => e.type == T).name; var result = false; for (var i = length - 1; i >= 0; i--) { // reverse iteration to avoid index shifting @@ -298,11 +277,7 @@ class MutableSubscriptionSet extends SubscriptionSet { } } } else { - realmCore.clearSubscriptionSet(this); + _handle.clear(); } } } - -extension MutableSubscriptionSetInternal on MutableSubscriptionSet { - MutableSubscriptionSetHandle get handle => _handle; -} From 877b99ef47e14d68dccd931e13ce894dd0527530 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Tue, 12 Mar 2024 10:09:53 +0100 Subject: [PATCH 02/68] Refactor: use import over part for handle_base.dart --- packages/realm_dart/lib/src/list.dart | 1 + packages/realm_dart/lib/src/map.dart | 1 + .../realm_dart/lib/src/native/convert.dart | 2 +- .../realm_dart/lib/src/native/decimal128.dart | 30 +- .../lib/src/native/error_handling.dart | 2 +- .../lib/src/native/handle_base.dart | 80 ++ .../mutable_subscription_set_handle.dart | 20 +- .../realm_dart/lib/src/native/realm_core.dart | 1013 +++++++---------- .../lib/src/native/realm_library.dart | 21 + .../lib/src/native/rooted_handle.dart | 39 + .../lib/src/native/subscription_handle.dart | 14 +- .../src/native/subscription_set_handle.dart | 30 +- packages/realm_dart/lib/src/realm_class.dart | 3 +- packages/realm_dart/lib/src/realm_object.dart | 2 + packages/realm_dart/lib/src/results.dart | 1 + packages/realm_dart/lib/src/set.dart | 1 + packages/realm_dart/lib/src/subscription.dart | 4 +- 17 files changed, 641 insertions(+), 623 deletions(-) create mode 100644 packages/realm_dart/lib/src/native/handle_base.dart create mode 100644 packages/realm_dart/lib/src/native/realm_library.dart create mode 100644 packages/realm_dart/lib/src/native/rooted_handle.dart diff --git a/packages/realm_dart/lib/src/list.dart b/packages/realm_dart/lib/src/list.dart index de5257ae4..41b4cb00f 100644 --- a/packages/realm_dart/lib/src/list.dart +++ b/packages/realm_dart/lib/src/list.dart @@ -9,6 +9,7 @@ import 'dart:ffi'; import 'package:collection/collection.dart' as collection; import 'collections.dart'; +import 'native/handle_base.dart'; import 'native/realm_core.dart'; import 'realm_class.dart'; import 'realm_object.dart'; diff --git a/packages/realm_dart/lib/src/map.dart b/packages/realm_dart/lib/src/map.dart index c7b9f7208..29a8b92be 100644 --- a/packages/realm_dart/lib/src/map.dart +++ b/packages/realm_dart/lib/src/map.dart @@ -9,6 +9,7 @@ import 'package:collection/collection.dart' as collection; import 'dart:ffi'; import 'collections.dart'; +import 'native/handle_base.dart'; import 'native/realm_core.dart'; import 'realm_object.dart'; import 'realm_class.dart'; diff --git a/packages/realm_dart/lib/src/native/convert.dart b/packages/realm_dart/lib/src/native/convert.dart index ae0c3f7cc..bdc39c290 100644 --- a/packages/realm_dart/lib/src/native/convert.dart +++ b/packages/realm_dart/lib/src/native/convert.dart @@ -4,7 +4,7 @@ part of 'realm_core.dart'; extension HandleBaseEx on T { - T? get nullPtrAsNull => _pointer == nullptr ? null : this; + T? get nullPtrAsNull => pointer == nullptr ? null : this; U? convert(U Function(T) convertor) => nullPtrAsNull.convert(convertor); } diff --git a/packages/realm_dart/lib/src/native/decimal128.dart b/packages/realm_dart/lib/src/native/decimal128.dart index 9d0039bbf..5c05eb5b8 100644 --- a/packages/realm_dart/lib/src/native/decimal128.dart +++ b/packages/realm_dart/lib/src/native/decimal128.dart @@ -15,7 +15,7 @@ class Decimal128 implements Comparable, common.Decimal128 { static final ten = Decimal128.fromInt(10); /// The value NaN. - static final nan = Decimal128._(_realmLib.realm_dart_decimal128_nan()); + static final nan = Decimal128._(realmLib.realm_dart_decimal128_nan()); /// The value +Inf. static final infinity = one / zero; // +Inf @@ -33,7 +33,7 @@ class Decimal128 implements Comparable, common.Decimal128 { static Decimal128? tryParse(String source) { if (!_validInput.hasMatch(source)) return null; return using((arena) { - final result = _realmLib.realm_dart_decimal128_from_string(source.toCharPtr(arena)); + final result = realmLib.realm_dart_decimal128_from_string(source.toCharPtr(arena)); return Decimal128._(result); }); } @@ -45,7 +45,7 @@ class Decimal128 implements Comparable, common.Decimal128 { /// Converts a `int` into a [Decimal128]. factory Decimal128.fromInt(int value) { - return Decimal128._(_realmLib.realm_dart_decimal128_from_int64(value)); + return Decimal128._(realmLib.realm_dart_decimal128_from_int64(value)); } /// Converts a `double` into a [Decimal128]. @@ -54,30 +54,30 @@ class Decimal128 implements Comparable, common.Decimal128 { } /// Returns `true` if `this` is NaN. - bool get isNaN => _realmLib.realm_dart_decimal128_is_nan(_value); + bool get isNaN => realmLib.realm_dart_decimal128_is_nan(_value); /// Adds `this` with `other` and returns a new [Decimal128]. Decimal128 operator +(Decimal128 other) { - return Decimal128._(_realmLib.realm_dart_decimal128_add(_value, other._value)); + return Decimal128._(realmLib.realm_dart_decimal128_add(_value, other._value)); } /// Subtracts `other` from `this` and returns a new [Decimal128]. Decimal128 operator -(Decimal128 other) { - return Decimal128._(_realmLib.realm_dart_decimal128_subtract(_value, other._value)); + return Decimal128._(realmLib.realm_dart_decimal128_subtract(_value, other._value)); } /// Multiplies `this` with `other` and returns a new [Decimal128]. Decimal128 operator *(Decimal128 other) { - return Decimal128._(_realmLib.realm_dart_decimal128_multiply(_value, other._value)); + return Decimal128._(realmLib.realm_dart_decimal128_multiply(_value, other._value)); } /// Divides `this` by `other` and returns a new [Decimal128]. Decimal128 operator /(Decimal128 other) { - return Decimal128._(_realmLib.realm_dart_decimal128_divide(_value, other._value)); + return Decimal128._(realmLib.realm_dart_decimal128_divide(_value, other._value)); } /// Negates `this` and returns a new [Decimal128]. - Decimal128 operator -() => Decimal128._(_realmLib.realm_dart_decimal128_negate(_value)); + Decimal128 operator -() => Decimal128._(realmLib.realm_dart_decimal128_negate(_value)); /// Returns the absolute value of `this`. Decimal128 abs() => this < zero ? -this : this; @@ -89,14 +89,14 @@ class Decimal128 implements Comparable, common.Decimal128 { // WARNING: Don't use identical to ensure nan != nan, // if (identical(this, other)) return true; if (other is Decimal128) { - return _realmLib.realm_dart_decimal128_equal(_value, other._value); + return realmLib.realm_dart_decimal128_equal(_value, other._value); } return false; } /// Returns `true` if `this` is less than `other`. bool operator <(Decimal128 other) { - return _realmLib.realm_dart_decimal128_less_than(_value, other._value); + return realmLib.realm_dart_decimal128_less_than(_value, other._value); } /// Returns `true` if `this` is less than or equal to `other`. @@ -104,27 +104,27 @@ class Decimal128 implements Comparable, common.Decimal128 { /// Returns `true` if `this` is greater than `other`. bool operator >(Decimal128 other) { - return _realmLib.realm_dart_decimal128_greater_than(_value, other._value); + return realmLib.realm_dart_decimal128_greater_than(_value, other._value); } /// Returns `true` if `this` is greater than or equal to `other`. bool operator >=(Decimal128 other) => compareTo(other) >= 0; /// Converts `this` to an `int`. Possibly loosing precision. - int toInt() => _realmLib.realm_dart_decimal128_to_int64(_value); + int toInt() => realmLib.realm_dart_decimal128_to_int64(_value); /// String representation of `this`. @override String toString() { return using((arena) { - final realmString = _realmLib.realm_dart_decimal128_to_string(_value); + final realmString = realmLib.realm_dart_decimal128_to_string(_value); return ascii.decode(realmString.data.cast().asTypedList(realmString.size)); }); } /// Compares `this` to `other`. @override - int compareTo(Decimal128 other) => _realmLib.realm_dart_decimal128_compare_to(_value, other._value); + int compareTo(Decimal128 other) => realmLib.realm_dart_decimal128_compare_to(_value, other._value); } extension Decimal128Internal on Decimal128 { diff --git a/packages/realm_dart/lib/src/native/error_handling.dart b/packages/realm_dart/lib/src/native/error_handling.dart index f18c9145d..f6242d92f 100644 --- a/packages/realm_dart/lib/src/native/error_handling.dart +++ b/packages/realm_dart/lib/src/native/error_handling.dart @@ -31,7 +31,7 @@ class LastError { LastError? getLastError(Allocator allocator) { final error = allocator(); - final success = _realmLib.realm_get_last_error(error); + final success = realmLib.realm_get_last_error(error); return success ? error.ref.toDart() : null; } diff --git a/packages/realm_dart/lib/src/native/handle_base.dart b/packages/realm_dart/lib/src/native/handle_base.dart new file mode 100644 index 000000000..df5c07ad6 --- /dev/null +++ b/packages/realm_dart/lib/src/native/handle_base.dart @@ -0,0 +1,80 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + +import 'dart:ffi'; + +import 'realm_library.dart'; + +// Flag to enable trace on finalization. +// +// Be aware that the trace is likely late, and it might in rare case be missing, +// as there are no absolute guarantees with Finalizer. +// +// It is often beneficial to also instrument the native realm_release to +// print the address released to get the exact time. +// +// This is const to allow the compiler to remove the trace code if not enabled. +const _enableFinalizerTrace = false; + +void _traceFinalization(Object o) { + print('Finalizing: $o'); +} + +final _debugFinalizer = Finalizer(_traceFinalization); + +void _setupFinalizationTrace(Object value, Object finalizationToken) { + _debugFinalizer.attach(value, finalizationToken, detach: value); +} + +void _tearDownFinalizationTrace(Object value, Object finalizationToken) { + _debugFinalizer.detach(value); + _traceFinalization(finalizationToken); +} + +abstract class HandleBase implements Finalizable { + late Pointer _finalizableHandle; + Pointer pointer; + bool get released => pointer == nullptr; + final bool isUnowned; + + @pragma('vm:never-inline') + void keepAlive() {} + + HandleBase(this.pointer, int size) : isUnowned = false { + _finalizableHandle = realmLib.realm_attach_finalizer(this, pointer.cast(), size); + + if (_enableFinalizerTrace) { + _setupFinalizationTrace(this, pointer); + } + } + + HandleBase.unowned(this.pointer) : isUnowned = true; + + @override + String toString() => "${pointer.toString()} value=${pointer.cast().value}${isUnowned ? ' (unowned)' : ''}"; + + /// @nodoc + /// A method that will be invoked just before the handle is released. Allows to cleanup + /// any custom data that inheritors are storing. + void releaseCore() {} + + void release() { + if (released) { + return; + } + + releaseCore(); + + if (!isUnowned) { + realmLib.realm_detach_finalizer(_finalizableHandle, this); + + realmLib.realm_release(pointer.cast()); + } + + pointer = nullptr; + + if (_enableFinalizerTrace) { + _tearDownFinalizationTrace(this, pointer); + } + } +} diff --git a/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart b/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart index 4da103287..3129f1ee2 100644 --- a/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart +++ b/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart @@ -6,9 +6,9 @@ part of 'realm_core.dart'; class MutableSubscriptionSetHandle extends SubscriptionSetHandle { MutableSubscriptionSetHandle._(Pointer pointer, RealmHandle root) : super._(pointer.cast(), root); - Pointer get _mutablePointer => super._pointer.cast(); + Pointer get _mutablePointer => super.pointer.cast(); - SubscriptionSetHandle commit() => SubscriptionSetHandle._(invokeGetPointer(() => _realmLib.realm_sync_subscription_set_commit(_mutablePointer)), _root); + SubscriptionSetHandle commit() => SubscriptionSetHandle._(invokeGetPointer(() => realmLib.realm_sync_subscription_set_commit(_mutablePointer)), _root); SubscriptionHandle insertOrAssignSubscription(RealmResults results, String? name, bool update) { if (!update) { @@ -19,9 +19,9 @@ class MutableSubscriptionSetHandle extends SubscriptionSetHandle { return using((arena) { final outIndex = arena(); final outInserted = arena(); - invokeGetBool(() => _realmLib.realm_sync_subscription_set_insert_or_assign_results( + invokeGetBool(() => realmLib.realm_sync_subscription_set_insert_or_assign_results( _mutablePointer, - results.handle._pointer, + results.handle.pointer, name?.toCharPtr(arena) ?? nullptr, outIndex, outInserted, @@ -30,10 +30,10 @@ class MutableSubscriptionSetHandle extends SubscriptionSetHandle { }); } - bool erase(Subscription subscription) { + bool erase(SubscriptionHandle subscription) { return using((arena) { final outErased = arena(); - invokeGetBool(() => _realmLib.realm_sync_subscription_set_erase_by_id( + invokeGetBool(() => realmLib.realm_sync_subscription_set_erase_by_id( _mutablePointer, subscription.id.toNative(arena), outErased, @@ -45,7 +45,7 @@ class MutableSubscriptionSetHandle extends SubscriptionSetHandle { bool eraseByName(String name) { return using((arena) { final outErased = arena(); - invokeGetBool(() => _realmLib.realm_sync_subscription_set_erase_by_name( + invokeGetBool(() => realmLib.realm_sync_subscription_set_erase_by_name( _mutablePointer, name.toCharPtr(arena), outErased, @@ -57,14 +57,14 @@ class MutableSubscriptionSetHandle extends SubscriptionSetHandle { bool eraseByResults(RealmResults results) { return using((arena) { final outErased = arena(); - invokeGetBool(() => _realmLib.realm_sync_subscription_set_erase_by_results( + invokeGetBool(() => realmLib.realm_sync_subscription_set_erase_by_results( _mutablePointer, - results.handle._pointer, + results.handle.pointer, outErased, )); return outErased.value; }); } - void clear() => invokeGetBool(() => _realmLib.realm_sync_subscription_set_clear(_mutablePointer)); + void clear() => invokeGetBool(() => realmLib.realm_sync_subscription_set_clear(_mutablePointer)); } diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index c7ad4edf4..0589b04fd 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -34,30 +34,20 @@ import '../results.dart'; import '../scheduler.dart'; import '../session.dart'; import '../set.dart'; -import '../subscription.dart'; +//import '../subscription.dart'; import '../user.dart'; import 'realm_bindings.dart'; +import 'realm_library.dart'; +import 'handle_base.dart'; -part 'decimal128.dart'; -part 'error_handling.dart'; // TODO: Use regular import +// TODO: Use regular part 'convert.dart'; +part 'decimal128.dart'; +part 'error_handling.dart'; +part 'mutable_subscription_set_handle.dart'; part 'subscription_handle.dart'; part 'subscription_set_handle.dart'; -part 'mutable_subscription_set_handle.dart'; - -const bugInTheSdkMessage = "This is likely a bug in the Realm SDK - please file an issue at https://github.com/realm/realm-dart/issues"; - -// This variable allows access to realm native library even before RealmCore is created. For Decimal128 for example -final _realmLib = () { - final result = RealmLibrary(initRealm()); - final nativeLibraryVersion = result.realm_dart_library_version().cast().toDartString(); - if (libraryVersion != nativeLibraryVersion) { - final additionMessage = - isFlutterPlatform ? bugInTheSdkMessage : "Did you forget to run `dart run realm_dart install` after upgrading the realm_dart package?"; - throw RealmException('Realm SDK package version does not match the native library version ($libraryVersion != $nativeLibraryVersion). $additionMessage'); - } - return result; -}(); +part 'rooted_handle.dart'; final _pluginLib = () { if (!isFlutterPlatform) { @@ -80,9 +70,6 @@ final _pluginLib = () { return pluginLib; }(); -// stamped into the library by the build system (see prepare-release.yml) -const libraryVersion = '2.3.0'; - _RealmCore realmCore = _RealmCore(); // All access to Realm Core functionality goes through this class @@ -181,26 +168,26 @@ class _RealmCore { schemaProperties.elementAt(i).value = properties; } - final schemaPtr = invokeGetPointer(() => _realmLib.realm_schema_new(schemaClasses, classCount, schemaProperties)); + final schemaPtr = invokeGetPointer(() => realmLib.realm_schema_new(schemaClasses, classCount, schemaProperties)); return SchemaHandle._(schemaPtr); }); } ConfigHandle _createConfig(Configuration config) { return using((Arena arena) { - final configPtr = _realmLib.realm_config_new(); + final configPtr = realmLib.realm_config_new(); final configHandle = ConfigHandle._(configPtr); if (config.schemaObjects.isNotEmpty) { final schemaHandle = _createSchema(config.schemaObjects); - _realmLib.realm_config_set_schema(configHandle._pointer, schemaHandle._pointer); + realmLib.realm_config_set_schema(configHandle.pointer, schemaHandle.pointer); } - _realmLib.realm_config_set_path(configHandle._pointer, config.path.toCharPtr(arena)); - _realmLib.realm_config_set_scheduler(configHandle._pointer, scheduler.handle._pointer); + realmLib.realm_config_set_path(configHandle.pointer, config.path.toCharPtr(arena)); + realmLib.realm_config_set_scheduler(configHandle.pointer, scheduler.handle.pointer); if (config.fifoFilesFallbackPath != null) { - _realmLib.realm_config_set_fifo_path(configHandle._pointer, config.fifoFilesFallbackPath!.toCharPtr(arena)); + realmLib.realm_config_set_fifo_path(configHandle.pointer, config.fifoFilesFallbackPath!.toCharPtr(arena)); } // Setting schema version only makes sense for local realms, but core insists it is always set, @@ -213,94 +200,94 @@ class _RealmCore { }; _realmLib.realm_config_set_schema_version(configHandle._pointer, schemaVersion); if (config.maxNumberOfActiveVersions != null) { - _realmLib.realm_config_set_max_number_of_active_versions(configHandle._pointer, config.maxNumberOfActiveVersions!); + realmLib.realm_config_set_max_number_of_active_versions(configHandle.pointer, config.maxNumberOfActiveVersions!); } if (config is LocalConfiguration) { //_realmLib.realm_config_set_schema_mode(configHandle._pointer, realm_schema_mode.RLM_SCHEMA_MODE_ADDITIVE_DISCOVERED); if (config.initialDataCallback != null) { - _realmLib.realm_config_set_data_initialization_function( - configHandle._pointer, + realmLib.realm_config_set_data_initialization_function( + configHandle.pointer, Pointer.fromFunction(initial_data_callback, false), config.toPersistentHandle(), - _realmLib.addresses.realm_dart_delete_persistent_handle, + realmLib.addresses.realm_dart_delete_persistent_handle, ); } if (config.isReadOnly) { - _realmLib.realm_config_set_schema_mode(configHandle._pointer, realm_schema_mode.RLM_SCHEMA_MODE_IMMUTABLE); + realmLib.realm_config_set_schema_mode(configHandle.pointer, realm_schema_mode.RLM_SCHEMA_MODE_IMMUTABLE); } else if (config.shouldDeleteIfMigrationNeeded) { - _realmLib.realm_config_set_schema_mode(configHandle._pointer, realm_schema_mode.RLM_SCHEMA_MODE_SOFT_RESET_FILE); + realmLib.realm_config_set_schema_mode(configHandle.pointer, realm_schema_mode.RLM_SCHEMA_MODE_SOFT_RESET_FILE); } if (config.disableFormatUpgrade) { - _realmLib.realm_config_set_disable_format_upgrade(configHandle._pointer, config.disableFormatUpgrade); + realmLib.realm_config_set_disable_format_upgrade(configHandle.pointer, config.disableFormatUpgrade); } if (config.shouldCompactCallback != null) { - _realmLib.realm_config_set_should_compact_on_launch_function( - configHandle._pointer, + realmLib.realm_config_set_should_compact_on_launch_function( + configHandle.pointer, Pointer.fromFunction(should_compact_callback, false), config.toPersistentHandle(), - _realmLib.addresses.realm_dart_delete_persistent_handle, + realmLib.addresses.realm_dart_delete_persistent_handle, ); } if (config.migrationCallback != null) { - _realmLib.realm_config_set_migration_function( - configHandle._pointer, + realmLib.realm_config_set_migration_function( + configHandle.pointer, Pointer.fromFunction(migration_callback, false), config.toPersistentHandle(), - _realmLib.addresses.realm_dart_delete_persistent_handle, + realmLib.addresses.realm_dart_delete_persistent_handle, ); } } else if (config is InMemoryConfiguration) { - _realmLib.realm_config_set_in_memory(configHandle._pointer, true); + realmLib.realm_config_set_in_memory(configHandle.pointer, true); } else if (config is FlexibleSyncConfiguration) { - _realmLib.realm_config_set_schema_mode(configHandle._pointer, realm_schema_mode.RLM_SCHEMA_MODE_ADDITIVE_DISCOVERED); - final syncConfigPtr = invokeGetPointer(() => _realmLib.realm_flx_sync_config_new(config.user.handle._pointer)); + realmLib.realm_config_set_schema_mode(configHandle.pointer, realm_schema_mode.RLM_SCHEMA_MODE_ADDITIVE_DISCOVERED); + final syncConfigPtr = invokeGetPointer(() => realmLib.realm_flx_sync_config_new(config.user.handle.pointer)); try { - _realmLib.realm_sync_config_set_session_stop_policy(syncConfigPtr, config.sessionStopPolicy.index); - _realmLib.realm_sync_config_set_resync_mode(syncConfigPtr, config.clientResetHandler.clientResyncMode.index); + realmLib.realm_sync_config_set_session_stop_policy(syncConfigPtr, config.sessionStopPolicy.index); + realmLib.realm_sync_config_set_resync_mode(syncConfigPtr, config.clientResetHandler.clientResyncMode.index); final errorHandlerCallback = Pointer.fromFunction, realm_sync_error_t)>(_syncErrorHandlerCallback); - final errorHandlerUserdata = _realmLib.realm_dart_userdata_async_new(config, errorHandlerCallback.cast(), scheduler.handle._pointer); - _realmLib.realm_sync_config_set_error_handler(syncConfigPtr, _realmLib.addresses.realm_dart_sync_error_handler_callback, errorHandlerUserdata.cast(), - _realmLib.addresses.realm_dart_userdata_async_free); + final errorHandlerUserdata = realmLib.realm_dart_userdata_async_new(config, errorHandlerCallback.cast(), scheduler.handle.pointer); + realmLib.realm_sync_config_set_error_handler(syncConfigPtr, realmLib.addresses.realm_dart_sync_error_handler_callback, errorHandlerUserdata.cast(), + realmLib.addresses.realm_dart_userdata_async_free); if (config.clientResetHandler.onBeforeReset != null) { final syncBeforeResetCallback = Pointer.fromFunction, Pointer)>(_syncBeforeResetCallback); - final beforeResetUserdata = _realmLib.realm_dart_userdata_async_new(config, syncBeforeResetCallback.cast(), scheduler.handle._pointer); + final beforeResetUserdata = realmLib.realm_dart_userdata_async_new(config, syncBeforeResetCallback.cast(), scheduler.handle.pointer); - _realmLib.realm_sync_config_set_before_client_reset_handler(syncConfigPtr, _realmLib.addresses.realm_dart_sync_before_reset_handler_callback, - beforeResetUserdata.cast(), _realmLib.addresses.realm_dart_userdata_async_free); + realmLib.realm_sync_config_set_before_client_reset_handler(syncConfigPtr, realmLib.addresses.realm_dart_sync_before_reset_handler_callback, + beforeResetUserdata.cast(), realmLib.addresses.realm_dart_userdata_async_free); } if (config.clientResetHandler.onAfterRecovery != null || config.clientResetHandler.onAfterDiscard != null) { final syncAfterResetCallback = Pointer.fromFunction, Pointer, Bool, Pointer)>( _syncAfterResetCallback); - final afterResetUserdata = _realmLib.realm_dart_userdata_async_new(config, syncAfterResetCallback.cast(), scheduler.handle._pointer); + final afterResetUserdata = realmLib.realm_dart_userdata_async_new(config, syncAfterResetCallback.cast(), scheduler.handle.pointer); - _realmLib.realm_sync_config_set_after_client_reset_handler(syncConfigPtr, _realmLib.addresses.realm_dart_sync_after_reset_handler_callback, - afterResetUserdata.cast(), _realmLib.addresses.realm_dart_userdata_async_free); + realmLib.realm_sync_config_set_after_client_reset_handler(syncConfigPtr, realmLib.addresses.realm_dart_sync_after_reset_handler_callback, + afterResetUserdata.cast(), realmLib.addresses.realm_dart_userdata_async_free); } if (config.shouldCompactCallback != null) { - _realmLib.realm_config_set_should_compact_on_launch_function( - configHandle._pointer, + realmLib.realm_config_set_should_compact_on_launch_function( + configHandle.pointer, Pointer.fromFunction(should_compact_callback, false), config.toPersistentHandle(), - _realmLib.addresses.realm_dart_delete_persistent_handle, + realmLib.addresses.realm_dart_delete_persistent_handle, ); } - _realmLib.realm_config_set_sync_config(configPtr, syncConfigPtr); + realmLib.realm_config_set_sync_config(configPtr, syncConfigPtr); } finally { - _realmLib.realm_release(syncConfigPtr.cast()); + realmLib.realm_release(syncConfigPtr.cast()); } } else if (config is DisconnectedSyncConfiguration) { - _realmLib.realm_config_set_schema_mode(configHandle._pointer, realm_schema_mode.RLM_SCHEMA_MODE_ADDITIVE_EXPLICIT); - _realmLib.realm_config_set_force_sync_history(configPtr, true); + realmLib.realm_config_set_schema_mode(configHandle.pointer, realm_schema_mode.RLM_SCHEMA_MODE_ADDITIVE_EXPLICIT); + realmLib.realm_config_set_force_sync_history(configPtr, true); } if (config.encryptionKey != null) { - _realmLib.realm_config_set_encryption_key(configPtr, config.encryptionKey!.toUint8Ptr(arena), encryptionKeySize); + realmLib.realm_config_set_encryption_key(configPtr, config.encryptionKey!.toUint8Ptr(arena), encryptionKeySize); } // For sync and for dynamic Realms, we need to have a complete view of the schema in Core. @@ -313,17 +300,17 @@ class _RealmCore { } String getPathForUser(User user) { - final syncConfigPtr = invokeGetPointer(() => _realmLib.realm_flx_sync_config_new(user.handle._pointer)); + final syncConfigPtr = invokeGetPointer(() => realmLib.realm_flx_sync_config_new(user.handle.pointer)); try { - final path = _realmLib.realm_app_sync_client_get_default_file_path_for_realm(syncConfigPtr, nullptr); + final path = realmLib.realm_app_sync_client_get_default_file_path_for_realm(syncConfigPtr, nullptr); return path.cast().toRealmDartString(freeRealmMemory: true)!; } finally { - _realmLib.realm_release(syncConfigPtr.cast()); + realmLib.realm_release(syncConfigPtr.cast()); } } SubscriptionSetHandle getSubscriptions(Realm realm) { - return SubscriptionSetHandle._(invokeGetPointer(() => _realmLib.realm_sync_get_active_subscription_set(realm.handle._pointer)), realm.handle); + return SubscriptionSetHandle._(invokeGetPointer(() => realmLib.realm_sync_get_active_subscription_set(realm.handle.pointer)), realm.handle); } static bool initial_data_callback(Pointer userdata, Pointer realmPtr) { @@ -334,7 +321,7 @@ class _RealmCore { config.initialDataCallback!(realm); return true; } catch (ex) { - _realmLib.realm_register_user_code_callback_error(ex.toPersistentHandle()); + realmLib.realm_register_user_code_callback_error(ex.toPersistentHandle()); } finally { realmHandle.release(); } @@ -361,7 +348,7 @@ class _RealmCore { try { final LocalConfiguration config = userdata.toObject(); - final oldSchemaVersion = _realmLib.realm_get_schema_version(oldRealmHandle); + final oldSchemaVersion = realmLib.realm_get_schema_version(oldRealmHandle); final oldConfig = Configuration.local([], path: config.path, isReadOnly: true, schemaVersion: oldSchemaVersion); final oldRealm = RealmInternal.getUnowned(oldConfig, oldHandle, isInMigration: true); @@ -371,7 +358,7 @@ class _RealmCore { config.migrationCallback!(migration, oldSchemaVersion); return true; } catch (ex) { - _realmLib.realm_register_user_code_callback_error(ex.toPersistentHandle()); + realmLib.realm_register_user_code_callback_error(ex.toPersistentHandle()); } finally { oldHandle.release(); newHandle.release(); @@ -400,7 +387,7 @@ class _RealmCore { } catch (error) { user_error = error.toPersistentHandle(); } finally { - _realmLib.realm_dart_invoke_unlock_callback(user_error, unlockCallbackFunc); + realmLib.realm_dart_invoke_unlock_callback(user_error, unlockCallbackFunc); } } @@ -429,7 +416,7 @@ class _RealmCore { } final beforeRealm = RealmInternal.getUnowned(syncConfig, RealmHandle._unowned(beforeHandle)); - final realmPtr = invokeGetPointer(() => _realmLib.realm_from_thread_safe_reference(afterReference, scheduler.handle._pointer)); + final realmPtr = invokeGetPointer(() => realmLib.realm_from_thread_safe_reference(afterReference, scheduler.handle.pointer)); final afterRealm = RealmInternal.getUnowned(syncConfig, RealmHandle._unowned(realmPtr)); try { @@ -444,33 +431,33 @@ class _RealmCore { void raiseError(Session session, int errorCode, bool isFatal) { using((arena) { final message = "Simulated session error".toCharPtr(arena); - _realmLib.realm_sync_session_handle_error_for_testing(session.handle._pointer, errorCode, message, isFatal); + realmLib.realm_sync_session_handle_error_for_testing(session.handle.pointer, errorCode, message, isFatal); }); } void realmDisableAutoRefreshForTesting(Realm realm) { - _realmLib.realm_set_auto_refresh(realm.handle._pointer, false); + realmLib.realm_set_auto_refresh(realm.handle.pointer, false); } SchedulerHandle createScheduler(int isolateId, int sendPort) { - final schedulerPtr = _realmLib.realm_dart_create_scheduler(isolateId, sendPort); + final schedulerPtr = realmLib.realm_dart_create_scheduler(isolateId, sendPort); return SchedulerHandle._(schedulerPtr); } void invokeScheduler(int workQueue) { final queuePointer = Pointer.fromAddress(workQueue); - _realmLib.realm_scheduler_perform_work(queuePointer); + realmLib.realm_scheduler_perform_work(queuePointer); } RealmHandle openRealm(Configuration config) { final configHandle = _createConfig(config); - final realmPtr = invokeGetPointer(() => _realmLib.realm_open(configHandle._pointer), "Error opening realm at path ${config.path}"); + final realmPtr = invokeGetPointer(() => realmLib.realm_open(configHandle.pointer), "Error opening realm at path ${config.path}"); return RealmHandle._(realmPtr); } RealmAsyncOpenTaskHandle createRealmAsyncOpenTask(FlexibleSyncConfiguration config) { final configHandle = _createConfig(config); - final asyncOpenTaskPtr = invokeGetPointer(() => _realmLib.realm_open_synchronized(configHandle._pointer), "Error opening realm at path ${config.path}"); + final asyncOpenTaskPtr = invokeGetPointer(() => realmLib.realm_open_synchronized(configHandle.pointer), "Error opening realm at path ${config.path}"); return RealmAsyncOpenTaskHandle._(asyncOpenTaskPtr); } @@ -479,12 +466,12 @@ class _RealmCore { if (!completer.isCancelled) { final callback = Pointer.fromFunction realm, Pointer error)>(_openRealmAsyncCallback); - final userData = _realmLib.realm_dart_userdata_async_new(completer, callback.cast(), scheduler.handle._pointer); - _realmLib.realm_async_open_task_start( - handle._pointer, - _realmLib.addresses.realm_dart_async_open_task_callback, + final userData = realmLib.realm_dart_userdata_async_new(completer, callback.cast(), scheduler.handle.pointer); + realmLib.realm_async_open_task_start( + handle.pointer, + realmLib.addresses.realm_dart_async_open_task_callback, userData.cast(), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, ); } return completer.future; @@ -498,29 +485,29 @@ class _RealmCore { } if (error != nullptr) { final err = arena(); - final lastError = _realmLib.realm_get_async_error(error, err) ? err.ref.toDart() : null; + final lastError = realmLib.realm_get_async_error(error, err) ? err.ref.toDart() : null; completer.completeError(RealmException("Failed to open realm: ${lastError?.message ?? 'Error details missing.'}")); return; } - final realmPtr = invokeGetPointer(() => _realmLib.realm_from_thread_safe_reference(realmSafePtr, scheduler.handle._pointer)); + final realmPtr = invokeGetPointer(() => realmLib.realm_from_thread_safe_reference(realmSafePtr, scheduler.handle.pointer)); completer.complete(RealmHandle._(realmPtr)); }); } void cancelOpenRealmAsync(RealmAsyncOpenTaskHandle handle) { - _realmLib.realm_async_open_task_cancel(handle._pointer); + realmLib.realm_async_open_task_cancel(handle.pointer); } RealmAsyncOpenTaskProgressNotificationTokenHandle realmAsyncOpenRegisterAsyncOpenProgressNotifier( RealmAsyncOpenTaskHandle handle, RealmAsyncOpenProgressNotificationsController controller) { final callback = Pointer.fromFunction(_syncProgressCallback); - final userdata = _realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle._pointer); - final tokenPtr = invokeGetPointer(() => _realmLib.realm_async_open_task_register_download_progress_notifier( - handle._pointer, - _realmLib.addresses.realm_dart_sync_progress_callback, + final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); + final tokenPtr = invokeGetPointer(() => realmLib.realm_async_open_task_register_download_progress_notifier( + handle.pointer, + realmLib.addresses.realm_dart_sync_progress_callback, userdata.cast(), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, )); return RealmAsyncOpenTaskProgressNotificationTokenHandle._(tokenPtr); } @@ -534,7 +521,7 @@ class _RealmCore { RealmSchema _readSchema(Realm realm, Arena arena, {int expectedSize = 10}) { final classesPtr = arena(expectedSize); final actualCount = arena(); - invokeGetBool(() => _realmLib.realm_get_class_keys(realm.handle._pointer, classesPtr, expectedSize, actualCount)); + invokeGetBool(() => realmLib.realm_get_class_keys(realm.handle.pointer, classesPtr, expectedSize, actualCount)); if (expectedSize < actualCount.value) { arena.free(classesPtr); return _readSchema(realm, arena, expectedSize: actualCount.value); @@ -544,7 +531,7 @@ class _RealmCore { for (var i = 0; i < actualCount.value; i++) { final classInfo = arena(); final classKey = classesPtr.elementAt(i).value; - invokeGetBool(() => _realmLib.realm_get_class(realm.handle._pointer, classKey, classInfo)); + invokeGetBool(() => realmLib.realm_get_class(realm.handle.pointer, classKey, classInfo)); final name = classInfo.ref.name.cast().toDartString(); final baseType = ObjectType.values.firstWhere((element) => element.flags == classInfo.ref.flags, @@ -560,7 +547,7 @@ class _RealmCore { SchemaObject _getSchemaForClassKey(Realm realm, int classKey, String name, ObjectType baseType, Arena arena, {int expectedSize = 10}) { final actualCount = arena(); final propertiesPtr = arena(expectedSize); - invokeGetBool(() => _realmLib.realm_get_class_properties(realm.handle._pointer, classKey, propertiesPtr, expectedSize, actualCount)); + invokeGetBool(() => realmLib.realm_get_class_properties(realm.handle.pointer, classKey, propertiesPtr, expectedSize, actualCount)); if (expectedSize < actualCount.value) { // The supplied array was too small - resize it @@ -595,17 +582,17 @@ class _RealmCore { void deleteRealmFiles(String path) { using((Arena arena) { final realm_deleted = arena(); - invokeGetBool(() => _realmLib.realm_delete_files(path.toCharPtr(arena), realm_deleted), "Error deleting realm at path $path"); + invokeGetBool(() => realmLib.realm_delete_files(path.toCharPtr(arena), realm_deleted), "Error deleting realm at path $path"); }); } String getFilesPath() { - return _realmLib.realm_dart_get_files_path().cast().toRealmDartString()!; + return realmLib.realm_dart_get_files_path().cast().toRealmDartString()!; } String getDeviceName() { if (Platform.isAndroid || Platform.isIOS) { - return _realmLib.realm_dart_get_device_name().cast().toRealmDartString()!; + return realmLib.realm_dart_get_device_name().cast().toRealmDartString()!; } return ""; @@ -613,30 +600,30 @@ class _RealmCore { String getDeviceVersion() { if (Platform.isAndroid || Platform.isIOS) { - return _realmLib.realm_dart_get_device_version().cast().toRealmDartString()!; + return realmLib.realm_dart_get_device_version().cast().toRealmDartString()!; } return ""; } String getRealmLibraryCpuArchitecture() { - return _realmLib.realm_get_library_cpu_arch().cast().toDartString(); + return realmLib.realm_get_library_cpu_arch().cast().toDartString(); } void closeRealm(Realm realm) { - invokeGetBool(() => _realmLib.realm_close(realm.handle._pointer), "Realm close failed"); + invokeGetBool(() => realmLib.realm_close(realm.handle.pointer), "Realm close failed"); } bool isRealmClosed(Realm realm) { - return _realmLib.realm_is_closed(realm.handle._pointer); + return realmLib.realm_is_closed(realm.handle.pointer); } void beginWrite(Realm realm) { - invokeGetBool(() => _realmLib.realm_begin_write(realm.handle._pointer), "Could not begin write"); + invokeGetBool(() => realmLib.realm_begin_write(realm.handle.pointer), "Could not begin write"); } void commitWrite(Realm realm) { - invokeGetBool(() => _realmLib.realm_commit(realm.handle._pointer), "Could not commit write"); + invokeGetBool(() => realmLib.realm_commit(realm.handle.pointer), "Could not commit write"); } Future beginWriteAsync(Realm realm, CancellationToken? ct) { @@ -649,11 +636,11 @@ class _RealmCore { if (ct?.isCancelled != true) { using((arena) { final transaction_id = arena(); - invokeGetBool(() => _realmLib.realm_async_begin_write( - realm.handle._pointer, + invokeGetBool(() => realmLib.realm_async_begin_write( + realm.handle.pointer, Pointer.fromFunction(_completeAsyncBeginWrite), completer.toPersistentHandle(), - _realmLib.addresses.realm_dart_delete_persistent_handle, + realmLib.addresses.realm_dart_delete_persistent_handle, true, transaction_id, )); @@ -673,11 +660,11 @@ class _RealmCore { if (ct?.isCancelled != true) { using((arena) { final transaction_id = arena(); - invokeGetBool(() => _realmLib.realm_async_commit( - realm.handle._pointer, + invokeGetBool(() => realmLib.realm_async_commit( + realm.handle.pointer, Pointer.fromFunction(_completeAsyncCommit), completer.toPersistentHandle(), - _realmLib.addresses.realm_dart_delete_persistent_handle, + realmLib.addresses.realm_dart_delete_persistent_handle, false, transaction_id, )); @@ -690,7 +677,7 @@ class _RealmCore { bool _cancelAsync(Realm realm, int cancellationId) { return using((Arena arena) { final didCancel = arena(); - invokeGetBool(() => _realmLib.realm_async_cancel(realm.handle._pointer, cancellationId, didCancel)); + invokeGetBool(() => realmLib.realm_async_cancel(realm.handle.pointer, cancellationId, didCancel)); return didCancel.value; }); } @@ -710,17 +697,17 @@ class _RealmCore { } bool getIsWritable(Realm realm) { - return _realmLib.realm_is_writable(realm.handle._pointer); + return realmLib.realm_is_writable(realm.handle.pointer); } void rollbackWrite(Realm realm) { - invokeGetBool(() => _realmLib.realm_rollback(realm.handle._pointer), "Could not rollback write"); + invokeGetBool(() => realmLib.realm_rollback(realm.handle.pointer), "Could not rollback write"); } bool realmRefresh(Realm realm) { return using((Arena arena) { final did_refresh = arena(); - invokeGetBool(() => _realmLib.realm_refresh(realm.handle._pointer, did_refresh), "Could not refresh"); + invokeGetBool(() => realmLib.realm_refresh(realm.handle.pointer, did_refresh), "Could not refresh"); return did_refresh.value; }); } @@ -728,9 +715,9 @@ class _RealmCore { Future realmRefreshAsync(Realm realm) async { final completer = Completer(); final callback = Pointer.fromFunction)>(_realmRefreshAsyncCallback); - Pointer completerPtr = _realmLib.realm_dart_object_to_persistent_handle(completer); - Pointer result = _realmLib.realm_add_realm_refresh_callback( - realm.handle._pointer, callback.cast(), completerPtr, _realmLib.addresses.realm_dart_delete_persistent_handle); + Pointer completerPtr = realmLib.realm_dart_object_to_persistent_handle(completer); + Pointer result = + realmLib.realm_add_realm_refresh_callback(realm.handle.pointer, callback.cast(), completerPtr, realmLib.addresses.realm_dart_delete_persistent_handle); if (result == nullptr) { return Future.value(false); @@ -744,7 +731,7 @@ class _RealmCore { return; } - final completer = _realmLib.realm_dart_persistent_handle_to_object(userdata) as Completer; + final completer = realmLib.realm_dart_persistent_handle_to_object(userdata) as Completer; completer.complete(true); } @@ -752,7 +739,7 @@ class _RealmCore { return using((Arena arena) { final found = arena(); final classInfo = arena(); - invokeGetBool(() => _realmLib.realm_find_class(realm.handle._pointer, schema.name.toCharPtr(arena), found, classInfo), + invokeGetBool(() => realmLib.realm_find_class(realm.handle.pointer, schema.name.toCharPtr(arena), found, classInfo), "Error getting class ${schema.name} from realm at ${realm.config.path}"); if (!found.value) { @@ -814,7 +801,7 @@ class _RealmCore { return using((Arena arena) { final parentPtr = arena>(); final classKeyPtr = arena(); - invokeGetBool(() => _realmLib.realm_object_get_parent(obj.handle._pointer, parentPtr, classKeyPtr)); + invokeGetBool(() => realmLib.realm_object_get_parent(obj.handle.pointer, parentPtr, classKeyPtr)); final handle = RealmObjectHandle._(parentPtr.value, obj.realm.handle); @@ -823,7 +810,7 @@ class _RealmCore { } int getClassKey(RealmObjectHandle handle) { - return _realmLib.realm_object_get_table(handle._pointer); + return realmLib.realm_object_get_table(handle.pointer); } RealmObjectHandle getOrCreateRealmObjectWithPrimaryKey(Realm realm, int classKey, Object? primaryKey) => @@ -835,36 +822,36 @@ class _RealmCore { Object? getProperty(RealmObjectBase object, int propertyKey) { return using((Arena arena) { final realm_value = arena(); - invokeGetBool(() => _realmLib.realm_get_value(object.handle._pointer, propertyKey, realm_value)); - return realm_value.toDartValue(object.realm, () => _realmLib.realm_get_list(object.handle._pointer, propertyKey), - () => _realmLib.realm_get_dictionary(object.handle._pointer, propertyKey)); + invokeGetBool(() => realmLib.realm_get_value(object.handle.pointer, propertyKey, realm_value)); + return realm_value.toDartValue(object.realm, () => realmLib.realm_get_list(object.handle.pointer, propertyKey), + () => realmLib.realm_get_dictionary(object.handle.pointer, propertyKey)); }); } void setProperty(RealmObjectBase object, int propertyKey, Object? value, bool isDefault) { using((Arena arena) { final realm_value = _toRealmValue(value, arena); - invokeGetBool(() => _realmLib.realm_set_value(object.handle._pointer, propertyKey, realm_value.ref, isDefault)); + invokeGetBool(() => realmLib.realm_set_value(object.handle.pointer, propertyKey, realm_value.ref, isDefault)); }); } void objectSetCollection(RealmObjectBase object, int propertyKey, RealmValue value) { - _createCollection(object.realm, value, () => _realmLib.realm_set_list(object.handle._pointer, propertyKey), - () => _realmLib.realm_set_dictionary(object.handle._pointer, propertyKey)); + _createCollection(object.realm, value, () => realmLib.realm_set_list(object.handle.pointer, propertyKey), + () => realmLib.realm_set_dictionary(object.handle.pointer, propertyKey)); } String objectToString(RealmObjectBase object) { - return _realmLib.realm_object_to_string(object.handle._pointer).cast().toRealmDartString(freeRealmMemory: true)!; + return realmLib.realm_object_to_string(object.handle.pointer).cast().toRealmDartString(freeRealmMemory: true)!; } // For debugging // ignore: unused_element - int get _threadId => _realmLib.realm_dart_get_thread_id(); + int get _threadId => realmLib.realm_dart_get_thread_id(); RealmObjectHandle? find(Realm realm, int classKey, Object? primaryKey) { return using((Arena arena) { final realm_value = _toRealmValue(primaryKey, arena); - final pointer = _realmLib.realm_object_find_with_primary_key(realm.handle._pointer, classKey, realm_value.ref, nullptr); + final pointer = realmLib.realm_object_find_with_primary_key(realm.handle.pointer, classKey, realm_value.ref, nullptr); if (pointer == nullptr) { return null; } @@ -874,32 +861,32 @@ class _RealmCore { } RealmObjectHandle? findExisting(Realm realm, int classKey, RealmObjectHandle other) { - final key = _realmLib.realm_object_get_key(other._pointer); - final pointer = invokeGetPointer(() => _realmLib.realm_get_object(realm.handle._pointer, classKey, key)); + final key = realmLib.realm_object_get_key(other.pointer); + final pointer = invokeGetPointer(() => realmLib.realm_get_object(realm.handle.pointer, classKey, key)); return RealmObjectHandle._(pointer, realm.handle); } void renameProperty(Realm realm, String objectType, String oldName, String newName, SchemaHandle schema) { using((Arena arena) { - invokeGetBool(() => _realmLib.realm_schema_rename_property( - realm.handle._pointer, schema._pointer, objectType.toCharPtr(arena), oldName.toCharPtr(arena), newName.toCharPtr(arena))); + invokeGetBool(() => realmLib.realm_schema_rename_property( + realm.handle.pointer, schema.pointer, objectType.toCharPtr(arena), oldName.toCharPtr(arena), newName.toCharPtr(arena))); }); } bool deleteType(Realm realm, String objectType) { return using((Arena arena) { final deletedPtr = arena(); - invokeGetBool(() => _realmLib.realm_remove_table(realm.handle._pointer, objectType.toCharPtr(arena), deletedPtr)); + invokeGetBool(() => realmLib.realm_remove_table(realm.handle.pointer, objectType.toCharPtr(arena), deletedPtr)); return deletedPtr.value; }); } void deleteRealmObject(RealmObjectBase object) { - invokeGetBool(() => _realmLib.realm_object_delete(object.handle._pointer)); + invokeGetBool(() => realmLib.realm_object_delete(object.handle.pointer)); } RealmResultsHandle findAll(Realm realm, int classKey) { - final pointer = invokeGetPointer(() => _realmLib.realm_object_find_all(realm.handle._pointer, classKey)); + final pointer = invokeGetPointer(() => realmLib.realm_object_find_all(realm.handle.pointer, classKey)); return RealmResultsHandle._(pointer, realm.handle); } @@ -912,8 +899,8 @@ class _RealmCore { } final queryHandle = _RealmQueryHandle._( invokeGetPointer( - () => _realmLib.realm_query_parse( - realm.handle._pointer, + () => realmLib.realm_query_parse( + realm.handle.pointer, classKey, query.toCharPtr(arena), length, @@ -934,8 +921,8 @@ class _RealmCore { } final queryHandle = _RealmQueryHandle._( invokeGetPointer( - () => _realmLib.realm_query_parse_for_results( - target.handle._pointer, + () => realmLib.realm_query_parse_for_results( + target.handle.pointer, query.toCharPtr(arena), length, argsPointer, @@ -948,7 +935,7 @@ class _RealmCore { RealmResultsHandle _queryFindAll(_RealmQueryHandle queryHandle) { try { - final resultsPointer = invokeGetPointer(() => _realmLib.realm_query_find_all(queryHandle._pointer)); + final resultsPointer = invokeGetPointer(() => realmLib.realm_query_find_all(queryHandle.pointer)); return RealmResultsHandle._(resultsPointer, queryHandle._root); } finally { queryHandle.release(); @@ -964,8 +951,8 @@ class _RealmCore { } final queryHandle = _RealmQueryHandle._( invokeGetPointer( - () => _realmLib.realm_query_parse_for_list( - target.handle._pointer, + () => realmLib.realm_query_parse_for_list( + target.handle.pointer, query.toCharPtr(arena), length, argsPointer, @@ -985,8 +972,8 @@ class _RealmCore { } final queryHandle = _RealmQueryHandle._( invokeGetPointer( - () => _realmLib.realm_query_parse_for_set( - target.handle._pointer, + () => realmLib.realm_query_parse_for_set( + target.handle.pointer, query.toCharPtr(arena), length, argsPointer, @@ -1008,8 +995,8 @@ class _RealmCore { final results = mapGetValues(target); final queryHandle = _RealmQueryHandle._( invokeGetPointer( - () => _realmLib.realm_query_parse_for_results( - results._pointer, + () => realmLib.realm_query_parse_for_results( + results.pointer, query.toCharPtr(arena), length, argsPointer, @@ -1021,21 +1008,21 @@ class _RealmCore { } RealmResultsHandle resultsFromList(RealmList list) { - final pointer = invokeGetPointer(() => _realmLib.realm_list_to_results(list.handle._pointer)); + final pointer = invokeGetPointer(() => realmLib.realm_list_to_results(list.handle.pointer)); return RealmResultsHandle._(pointer, list.realm.handle); } RealmResultsHandle resultsFromSet(RealmSet set) { - final pointer = invokeGetPointer(() => _realmLib.realm_set_to_results(set.handle._pointer)); + final pointer = invokeGetPointer(() => realmLib.realm_set_to_results(set.handle.pointer)); return RealmResultsHandle._(pointer, set.realm.handle); } Object? resultsGetElementAt(RealmResults results, int index) { return using((Arena arena) { final realm_value = arena(); - invokeGetBool(() => _realmLib.realm_results_get(results.handle._pointer, index, realm_value)); - return realm_value.toDartValue(results.realm, () => _realmLib.realm_results_get_list(results.handle._pointer, index), - () => _realmLib.realm_results_get_dictionary(results.handle._pointer, index)); + invokeGetBool(() => realmLib.realm_results_get(results.handle.pointer, index, realm_value)); + return realm_value.toDartValue(results.realm, () => realmLib.realm_results_get_list(results.handle.pointer, index), + () => realmLib.realm_results_get_dictionary(results.handle.pointer, index)); }); } @@ -1047,8 +1034,8 @@ class _RealmCore { // TODO: how should this behave for collections final realm_value = _toRealmValue(value, arena); invokeGetBool( - () => _realmLib.realm_results_find( - results.handle._pointer, + () => realmLib.realm_results_find( + results.handle.pointer, realm_value, out_index, out_found, @@ -1059,14 +1046,14 @@ class _RealmCore { } RealmObjectHandle resultsGetObjectAt(RealmResults results, int index) { - final pointer = invokeGetPointer(() => _realmLib.realm_results_get_object(results.handle._pointer, index)); + final pointer = invokeGetPointer(() => realmLib.realm_results_get_object(results.handle.pointer, index)); return RealmObjectHandle._(pointer, results.realm.handle); } int getResultsCount(RealmResults results) { return using((Arena arena) { final countPtr = arena(); - invokeGetBool(() => _realmLib.realm_results_count(results.handle._pointer, countPtr)); + invokeGetBool(() => realmLib.realm_results_count(results.handle.pointer, countPtr)); return countPtr.value; }); } @@ -1074,7 +1061,7 @@ class _RealmCore { bool resultsIsValid(RealmResults results) { return using((arena) { final is_valid = arena(); - invokeGetBool(() => _realmLib.realm_results_is_valid(results.handle._pointer, is_valid)); + invokeGetBool(() => realmLib.realm_results_is_valid(results.handle.pointer, is_valid)); return is_valid.value; }); } @@ -1087,8 +1074,8 @@ class _RealmCore { final out_num_moves = arena(); final out_collection_cleared = arena(); final out_collection_was_deleted = arena(); - _realmLib.realm_collection_changes_get_num_changes( - changes._pointer, + realmLib.realm_collection_changes_get_num_changes( + changes.pointer, out_num_deletions, out_num_insertions, out_num_modifications, @@ -1108,8 +1095,8 @@ class _RealmCore { final out_modification_indexes_after = arena(modificationCount); final out_moves = arena(moveCount); - _realmLib.realm_collection_changes_get_changes( - changes._pointer, + realmLib.realm_collection_changes_get_changes( + changes.pointer, out_deletion_indexes, deletionsCount, out_insertion_indexes, @@ -1147,8 +1134,8 @@ class _RealmCore { final out_num_insertions = arena(); final out_num_modifications = arena(); final out_collection_was_deleted = arena(); - _realmLib.realm_dictionary_get_changes( - changes._pointer, + realmLib.realm_dictionary_get_changes( + changes.pointer, out_num_deletions, out_num_insertions, out_num_modifications, @@ -1164,8 +1151,8 @@ class _RealmCore { final out_modification_indexes = arena(modificationCount); final out_collection_was_cleared = arena(); - _realmLib.realm_dictionary_get_changed_keys( - changes._pointer, + realmLib.realm_dictionary_get_changed_keys( + changes.pointer, out_deletion_indexes, out_num_deletions, out_insertion_indexes, @@ -1181,29 +1168,29 @@ class _RealmCore { } _RealmLinkHandle _getObjectAsLink(RealmObjectBase object) { - final realmLink = _realmLib.realm_object_as_link(object.handle._pointer); + final realmLink = realmLib.realm_object_as_link(object.handle.pointer); return _RealmLinkHandle._(realmLink); } RealmObjectHandle _getObject(Realm realm, int classKey, int objectKey) { - final pointer = invokeGetPointer(() => _realmLib.realm_get_object(realm.handle._pointer, classKey, objectKey)); + final pointer = invokeGetPointer(() => realmLib.realm_get_object(realm.handle.pointer, classKey, objectKey)); return RealmObjectHandle._(pointer, realm.handle); } RealmListHandle getListProperty(RealmObjectBase object, int propertyKey) { - final pointer = invokeGetPointer(() => _realmLib.realm_get_list(object.handle._pointer, propertyKey)); + final pointer = invokeGetPointer(() => realmLib.realm_get_list(object.handle.pointer, propertyKey)); return RealmListHandle._(pointer, object.realm.handle); } RealmResultsHandle getBacklinks(RealmObjectBase object, int sourceTableKey, int propertyKey) { - final pointer = invokeGetPointer(() => _realmLib.realm_get_backlinks(object.handle._pointer, sourceTableKey, propertyKey)); + final pointer = invokeGetPointer(() => realmLib.realm_get_backlinks(object.handle.pointer, sourceTableKey, propertyKey)); return RealmResultsHandle._(pointer, object.realm.handle); } int getListSize(RealmListHandle handle) { return using((Arena arena) { final size = arena(); - invokeGetBool(() => _realmLib.realm_list_size(handle._pointer, size)); + invokeGetBool(() => realmLib.realm_list_size(handle.pointer, size)); return size.value; }); } @@ -1211,44 +1198,44 @@ class _RealmCore { Object? listGetElementAt(RealmList list, int index) { return using((Arena arena) { final realm_value = arena(); - invokeGetBool(() => _realmLib.realm_list_get(list.handle._pointer, index, realm_value)); + invokeGetBool(() => realmLib.realm_list_get(list.handle.pointer, index, realm_value)); return realm_value.toDartValue( - list.realm, () => _realmLib.realm_list_get_list(list.handle._pointer, index), () => _realmLib.realm_list_get_dictionary(list.handle._pointer, index)); + list.realm, () => realmLib.realm_list_get_list(list.handle.pointer, index), () => realmLib.realm_list_get_dictionary(list.handle.pointer, index)); }); } void listAddElementAt(RealmListHandle handle, int index, Object? value, bool insert) { using((Arena arena) { final realm_value = _toRealmValue(value, arena); - invokeGetBool(() => (insert ? _realmLib.realm_list_insert : _realmLib.realm_list_set)(handle._pointer, index, realm_value.ref)); + invokeGetBool(() => (insert ? realmLib.realm_list_insert : realmLib.realm_list_set)(handle.pointer, index, realm_value.ref)); }); } void listAddCollectionAt(RealmListHandle handle, Realm realm, int index, RealmValue value, bool insert) { - _createCollection(realm, value, () => (insert ? _realmLib.realm_list_insert_list : _realmLib.realm_list_set_list)(handle._pointer, index), - () => (insert ? _realmLib.realm_list_insert_dictionary : _realmLib.realm_list_set_dictionary)(handle._pointer, index)); + _createCollection(realm, value, () => (insert ? realmLib.realm_list_insert_list : realmLib.realm_list_set_list)(handle.pointer, index), + () => (insert ? realmLib.realm_list_insert_dictionary : realmLib.realm_list_set_dictionary)(handle.pointer, index)); } RealmObjectHandle listSetEmbeddedObjectAt(Realm realm, RealmListHandle handle, int index) { - final ptr = invokeGetPointer(() => _realmLib.realm_list_set_embedded(handle._pointer, index)); + final ptr = invokeGetPointer(() => realmLib.realm_list_set_embedded(handle.pointer, index)); return RealmObjectHandle._(ptr, realm.handle); } RealmObjectHandle listInsertEmbeddedObjectAt(Realm realm, RealmListHandle handle, int index) { - final ptr = invokeGetPointer(() => _realmLib.realm_list_insert_embedded(handle._pointer, index)); + final ptr = invokeGetPointer(() => realmLib.realm_list_insert_embedded(handle.pointer, index)); return RealmObjectHandle._(ptr, realm.handle); } void listRemoveElementAt(RealmListHandle handle, int index) { - invokeGetBool(() => _realmLib.realm_list_erase(handle._pointer, index)); + invokeGetBool(() => realmLib.realm_list_erase(handle.pointer, index)); } void listMoveElement(RealmListHandle handle, int from, int to) { - invokeGetBool(() => _realmLib.realm_list_move(handle._pointer, from, to)); + invokeGetBool(() => realmLib.realm_list_move(handle.pointer, from, to)); } void listDeleteAll(RealmList list) { - invokeGetBool(() => _realmLib.realm_list_remove_all(list.handle._pointer)); + invokeGetBool(() => realmLib.realm_list_remove_all(list.handle.pointer)); } int listFind(RealmList list, Object? value) { @@ -1259,8 +1246,8 @@ class _RealmCore { // TODO: how should this behave for collections final realm_value = _toRealmValue(value, arena); invokeGetBool( - () => _realmLib.realm_list_find( - list.handle._pointer, + () => realmLib.realm_list_find( + list.handle.pointer, realm_value, out_index, out_found, @@ -1271,15 +1258,15 @@ class _RealmCore { } void resultsDeleteAll(RealmResults results) { - invokeGetBool(() => _realmLib.realm_results_delete_all(results.handle._pointer)); + invokeGetBool(() => realmLib.realm_results_delete_all(results.handle.pointer)); } void listClear(RealmListHandle listHandle) { - invokeGetBool(() => _realmLib.realm_list_clear(listHandle._pointer)); + invokeGetBool(() => realmLib.realm_list_clear(listHandle.pointer)); } RealmSetHandle getSetProperty(RealmObjectBase object, int propertyKey) { - final pointer = invokeGetPointer(() => _realmLib.realm_get_set(object.handle._pointer, propertyKey)); + final pointer = invokeGetPointer(() => realmLib.realm_get_set(object.handle.pointer, propertyKey)); return RealmSetHandle._(pointer, object.realm.handle); } @@ -1288,7 +1275,7 @@ class _RealmCore { final realm_value = _toRealmValue(value, arena); final out_index = arena(); final out_inserted = arena(); - invokeGetBool(() => _realmLib.realm_set_insert(handle._pointer, realm_value.ref, out_index, out_inserted)); + invokeGetBool(() => realmLib.realm_set_insert(handle.pointer, realm_value.ref, out_index, out_inserted)); return out_inserted.value; }); } @@ -1296,7 +1283,7 @@ class _RealmCore { Object? realmSetGetElementAt(RealmSet realmSet, int index) { return using((Arena arena) { final realm_value = arena(); - invokeGetBool(() => _realmLib.realm_set_get(realmSet.handle._pointer, index, realm_value)); + invokeGetBool(() => realmLib.realm_set_get(realmSet.handle.pointer, index, realm_value)); final result = realm_value.toDartValue( realmSet.realm, () => throw RealmException('Sets cannot contain collections'), () => throw RealmException('Sets cannot contain collections')); return result; @@ -1309,7 +1296,7 @@ class _RealmCore { final realm_value = _toRealmValue(value, arena); final out_index = arena(); final out_found = arena(); - invokeGetBool(() => _realmLib.realm_set_find(realmSet.handle._pointer, realm_value.ref, out_index, out_found)); + invokeGetBool(() => realmLib.realm_set_find(realmSet.handle.pointer, realm_value.ref, out_index, out_found)); return out_found.value; }); } @@ -1319,36 +1306,36 @@ class _RealmCore { // TODO: do we support sets containing mixed collections final realm_value = _toRealmValue(value, arena); final out_erased = arena(); - invokeGetBool(() => _realmLib.realm_set_erase(realmSet.handle._pointer, realm_value.ref, out_erased)); + invokeGetBool(() => realmLib.realm_set_erase(realmSet.handle.pointer, realm_value.ref, out_erased)); return out_erased.value; }); } void realmSetClear(RealmSetHandle handle) { - invokeGetBool(() => _realmLib.realm_set_clear(handle._pointer)); + invokeGetBool(() => realmLib.realm_set_clear(handle.pointer)); } int realmSetSize(RealmSet realmSet) { return using((Arena arena) { final out_size = arena(); - invokeGetBool(() => _realmLib.realm_set_size(realmSet.handle._pointer, out_size)); + invokeGetBool(() => realmLib.realm_set_size(realmSet.handle.pointer, out_size)); return out_size.value; }); } bool realmSetIsValid(RealmSet realmSet) { - return _realmLib.realm_set_is_valid(realmSet.handle._pointer); + return realmLib.realm_set_is_valid(realmSet.handle.pointer); } void realmSetRemoveAll(RealmSet realmSet) { - invokeGetBool(() => _realmLib.realm_set_remove_all(realmSet.handle._pointer)); + invokeGetBool(() => realmLib.realm_set_remove_all(realmSet.handle.pointer)); } RealmNotificationTokenHandle subscribeSetNotifications(RealmSet realmSet, NotificationsController controller) { - final pointer = invokeGetPointer(() => _realmLib.realm_set_add_notification_callback( - realmSet.handle._pointer, + final pointer = invokeGetPointer(() => realmLib.realm_set_add_notification_callback( + realmSet.handle.pointer, controller.toPersistentHandle(), - _realmLib.addresses.realm_dart_delete_persistent_handle, + realmLib.addresses.realm_dart_delete_persistent_handle, nullptr, Pointer.fromFunction(collection_change_callback), )); @@ -1359,7 +1346,7 @@ class _RealmCore { int mapGetSize(RealmMapHandle handle) { return using((Arena arena) { final size = arena(); - invokeGetBool(() => _realmLib.realm_dictionary_size(handle._pointer, size)); + invokeGetBool(() => realmLib.realm_dictionary_size(handle.pointer, size)); return size.value; }); } @@ -1368,7 +1355,7 @@ class _RealmCore { return using((Arena arena) { final keyValue = _toRealmValue(key, arena); final out_erased = arena(); - invokeGetBool(() => _realmLib.realm_dictionary_erase(handle._pointer, keyValue.ref, out_erased)); + invokeGetBool(() => realmLib.realm_dictionary_erase(handle.pointer, keyValue.ref, out_erased)); return out_erased.value; }); } @@ -1378,10 +1365,10 @@ class _RealmCore { final realm_value = arena(); final key_value = _toRealmValue(key, arena); final out_found = arena(); - invokeGetBool(() => _realmLib.realm_dictionary_find(map.handle._pointer, key_value.ref, realm_value, out_found)); + invokeGetBool(() => realmLib.realm_dictionary_find(map.handle.pointer, key_value.ref, realm_value, out_found)); if (out_found.value) { - return realm_value.toDartValue(map.realm, () => _realmLib.realm_dictionary_get_list(map.handle._pointer, key_value.ref), - () => _realmLib.realm_dictionary_get_dictionary(map.handle._pointer, key_value.ref)); + return realm_value.toDartValue(map.realm, () => realmLib.realm_dictionary_get_list(map.handle.pointer, key_value.ref), + () => realmLib.realm_dictionary_get_dictionary(map.handle.pointer, key_value.ref)); } return null; @@ -1389,24 +1376,24 @@ class _RealmCore { } bool mapIsValid(RealmMap map) { - return _realmLib.realm_dictionary_is_valid(map.handle._pointer); + return realmLib.realm_dictionary_is_valid(map.handle.pointer); } void mapClear(RealmMapHandle mapHandle) { - invokeGetBool(() => _realmLib.realm_dictionary_clear(mapHandle._pointer)); + invokeGetBool(() => realmLib.realm_dictionary_clear(mapHandle.pointer)); } RealmResultsHandle mapGetKeys(ManagedRealmMap map) { return using((Arena arena) { final out_size = arena(); final out_keys = arena>(); - invokeGetBool(() => _realmLib.realm_dictionary_get_keys(map.handle._pointer, out_size, out_keys)); + invokeGetBool(() => realmLib.realm_dictionary_get_keys(map.handle.pointer, out_size, out_keys)); return RealmResultsHandle._(out_keys.value, map.realm.handle); }); } RealmResultsHandle mapGetValues(ManagedRealmMap map) { - final result = invokeGetPointer(() => _realmLib.realm_dictionary_to_results(map.handle._pointer)); + final result = invokeGetPointer(() => realmLib.realm_dictionary_to_results(map.handle.pointer)); return RealmResultsHandle._(result, map.realm.handle); } @@ -1414,7 +1401,7 @@ class _RealmCore { return using((Arena arena) { final key_value = _toRealmValue(key, arena); final out_found = arena(); - invokeGetBool(() => _realmLib.realm_dictionary_contains_key(map.handle._pointer, key_value.ref, out_found)); + invokeGetBool(() => realmLib.realm_dictionary_contains_key(map.handle.pointer, key_value.ref, out_found)); return out_found.value; }); } @@ -1424,7 +1411,7 @@ class _RealmCore { // TODO: how should this behave for collections final value_value = _toRealmValue(value, arena); final out_index = arena(); - invokeGetBool(() => _realmLib.realm_dictionary_contains_value(map.handle._pointer, value_value.ref, out_index)); + invokeGetBool(() => realmLib.realm_dictionary_contains_value(map.handle.pointer, value_value.ref, out_index)); return out_index.value > -1; }); } @@ -1432,7 +1419,7 @@ class _RealmCore { RealmObjectHandle mapInsertEmbeddedObject(Realm realm, RealmMapHandle handle, String key) { return using((Arena arena) { final realm_value = _toRealmValue(key, arena); - final ptr = invokeGetPointer(() => _realmLib.realm_dictionary_insert_embedded(handle._pointer, realm_value.ref)); + final ptr = invokeGetPointer(() => realmLib.realm_dictionary_insert_embedded(handle.pointer, realm_value.ref)); return RealmObjectHandle._(ptr, realm.handle); }); } @@ -1441,31 +1428,30 @@ class _RealmCore { using((Arena arena) { final key_value = _toRealmValue(key, arena); final value_value = _toRealmValue(value, arena); - invokeGetBool(() => _realmLib.realm_dictionary_insert(handle._pointer, key_value.ref, value_value.ref, nullptr, nullptr)); + invokeGetBool(() => realmLib.realm_dictionary_insert(handle.pointer, key_value.ref, value_value.ref, nullptr, nullptr)); }); } void mapInsertCollection(RealmMapHandle handle, Realm realm, String key, RealmValue value) { using((Arena arena) { final key_value = _toRealmValue(key, arena); - _createCollection(realm, value, () => _realmLib.realm_dictionary_insert_list(handle._pointer, key_value.ref), - () => _realmLib.realm_dictionary_insert_dictionary(handle._pointer, key_value.ref)); + _createCollection(realm, value, () => realmLib.realm_dictionary_insert_list(handle.pointer, key_value.ref), + () => realmLib.realm_dictionary_insert_dictionary(handle.pointer, key_value.ref)); }); } RealmMapHandle getMapProperty(RealmObjectBase object, int propertyKey) { - final pointer = invokeGetPointer(() => _realmLib.realm_get_dictionary(object.handle._pointer, propertyKey)); + final pointer = invokeGetPointer(() => realmLib.realm_get_dictionary(object.handle.pointer, propertyKey)); return RealmMapHandle._(pointer, object.realm.handle); } bool _equals(HandleBase first, HandleBase second) { - return _realmLib.realm_equals(first._pointer.cast(), second._pointer.cast()); + return realmLib.realm_equals(first.pointer.cast(), second.pointer.cast()); } bool objectEquals(RealmObjectBase first, RealmObjectBase second) => _equals(first.handle, second.handle); bool realmEquals(Realm first, Realm second) => _equals(first.handle, second.handle); bool userEquals(User first, User second) => _equals(first.handle, second.handle); - bool subscriptionEquals(Subscription first, Subscription second) => _equals(first.handle, second.handle); int objectGetHashCode(RealmObjectBase value) { final link = realmCore._getObjectAsLink(value); @@ -1477,16 +1463,16 @@ class _RealmCore { } RealmResultsHandle resultsSnapshot(RealmResults results) { - final resultsPointer = invokeGetPointer(() => _realmLib.realm_results_snapshot(results.handle._pointer)); + final resultsPointer = invokeGetPointer(() => realmLib.realm_results_snapshot(results.handle.pointer)); return RealmResultsHandle._(resultsPointer, results.realm.handle); } bool objectIsValid(RealmObjectBase object) { - return _realmLib.realm_object_is_valid(object.handle._pointer); + return realmLib.realm_object_is_valid(object.handle.pointer); } bool listIsValid(RealmList list) { - return _realmLib.realm_list_is_valid(list.handle._pointer); + return realmLib.realm_list_is_valid(list.handle.pointer); } static void collection_change_callback(Pointer userdata, Pointer data) { @@ -1498,7 +1484,7 @@ class _RealmCore { } try { - final clonedData = _realmLib.realm_clone(data.cast()); + final clonedData = realmLib.realm_clone(data.cast()); if (clonedData == nullptr) { controller.onError(RealmError("Error while cloning notifications data")); return; @@ -1520,7 +1506,7 @@ class _RealmCore { } try { - final clonedData = _realmLib.realm_clone(data.cast()); + final clonedData = realmLib.realm_clone(data.cast()); if (clonedData == nullptr) { controller.onError(RealmError("Error while cloning notifications data")); return; @@ -1542,7 +1528,7 @@ class _RealmCore { } try { - final clonedData = _realmLib.realm_clone(data.cast()); + final clonedData = realmLib.realm_clone(data.cast()); if (clonedData == nullptr) { controller.onError(RealmError("Error while cloning notifications data")); return; @@ -1571,10 +1557,10 @@ class _RealmCore { } RealmNotificationTokenHandle subscribeResultsNotifications(RealmResults results, NotificationsController controller) { - final pointer = invokeGetPointer(() => _realmLib.realm_results_add_notification_callback( - results.handle._pointer, + final pointer = invokeGetPointer(() => realmLib.realm_results_add_notification_callback( + results.handle.pointer, controller.toPersistentHandle(), - _realmLib.addresses.realm_dart_delete_persistent_handle, + realmLib.addresses.realm_dart_delete_persistent_handle, nullptr, Pointer.fromFunction(collection_change_callback), )); @@ -1583,10 +1569,10 @@ class _RealmCore { } RealmNotificationTokenHandle subscribeListNotifications(RealmList list, NotificationsController controller) { - final pointer = invokeGetPointer(() => _realmLib.realm_list_add_notification_callback( - list.handle._pointer, + final pointer = invokeGetPointer(() => realmLib.realm_list_add_notification_callback( + list.handle.pointer, controller.toPersistentHandle(), - _realmLib.addresses.realm_dart_delete_persistent_handle, + realmLib.addresses.realm_dart_delete_persistent_handle, nullptr, Pointer.fromFunction(collection_change_callback), )); @@ -1597,10 +1583,10 @@ class _RealmCore { RealmNotificationTokenHandle subscribeObjectNotifications(RealmObjectBase object, NotificationsController controller, [List? keyPaths]) { return using((Arena arena) { final kpNative = buildAndVerifyKeyPath(object, keyPaths); - final pointer = invokeGetPointer(() => _realmLib.realm_object_add_notification_callback( + final pointer = invokeGetPointer(() => realmLib.realm_object_add_notification_callback( object.handle._pointer, controller.toPersistentHandle(), - _realmLib.addresses.realm_dart_delete_persistent_handle, + realmLib.addresses.realm_dart_delete_persistent_handle, kpNative, Pointer.fromFunction(object_change_callback), )); @@ -1623,15 +1609,15 @@ class _RealmCore { keypathsNative[i] = keyPaths[i].toCharPtr(arena); } - return invokeGetPointer(() => _realmLib.realm_create_key_path_array(object.realm.handle._pointer, classKey, length, keypathsNative)); + return invokeGetPointer(() => realmLib.realm_create_key_path_array(object.realm.handle._pointer, classKey, length, keypathsNative)); }); } RealmNotificationTokenHandle subscribeMapNotifications(RealmMap map, NotificationsController controller) { - final pointer = invokeGetPointer(() => _realmLib.realm_dictionary_add_notification_callback( - map.handle._pointer, + final pointer = invokeGetPointer(() => realmLib.realm_dictionary_add_notification_callback( + map.handle.pointer, controller.toPersistentHandle(), - _realmLib.addresses.realm_dart_delete_persistent_handle, + realmLib.addresses.realm_dart_delete_persistent_handle, nullptr, Pointer.fromFunction(map_change_callback), )); @@ -1641,12 +1627,12 @@ class _RealmCore { UserNotificationTokenHandle subscribeUserNotifications(UserNotificationsController controller) { final callback = Pointer.fromFunction(user_change_callback); - final userdata = _realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle._pointer); - final notification_token = _realmLib.realm_sync_user_on_state_change_register_callback( - controller.user.handle._pointer, - _realmLib.addresses.realm_dart_user_change_callback, + final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); + final notification_token = realmLib.realm_sync_user_on_state_change_register_callback( + controller.user.handle.pointer, + realmLib.addresses.realm_dart_user_change_callback, userdata.cast(), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, ); return UserNotificationTokenHandle._(notification_token); } @@ -1659,15 +1645,15 @@ class _RealmCore { } bool getObjectChangesIsDeleted(RealmObjectChangesHandle handle) { - return _realmLib.realm_object_changes_is_deleted(handle._pointer); + return realmLib.realm_object_changes_is_deleted(handle.pointer); } List getObjectChangesProperties(RealmObjectChangesHandle handle) { return using((arena) { - final count = _realmLib.realm_object_changes_get_num_modified_properties(handle._pointer); + final count = realmLib.realm_object_changes_get_num_modified_properties(handle.pointer); final out_modified = arena(count); - _realmLib.realm_object_changes_get_modified_properties(handle._pointer, out_modified, count); + realmLib.realm_object_changes_get_modified_properties(handle.pointer, out_modified, count); return out_modified.asTypedList(count).toList(); }); @@ -1676,27 +1662,27 @@ class _RealmCore { AppConfigHandle _createAppConfig(AppConfiguration configuration, RealmHttpTransportHandle httpTransport) { return using((arena) { final app_id = configuration.appId.toCharPtr(arena); - final handle = AppConfigHandle._(_realmLib.realm_app_config_new(app_id, httpTransport._pointer)); + final handle = AppConfigHandle._(realmLib.realm_app_config_new(app_id, httpTransport.pointer)); - _realmLib.realm_app_config_set_platform_version(handle._pointer, Platform.operatingSystemVersion.toCharPtr(arena)); + realmLib.realm_app_config_set_platform_version(handle.pointer, Platform.operatingSystemVersion.toCharPtr(arena)); - _realmLib.realm_app_config_set_sdk(handle._pointer, 'Dart'.toCharPtr(arena)); - _realmLib.realm_app_config_set_sdk_version(handle._pointer, libraryVersion.toCharPtr(arena)); + realmLib.realm_app_config_set_sdk(handle.pointer, 'Dart'.toCharPtr(arena)); + realmLib.realm_app_config_set_sdk_version(handle.pointer, libraryVersion.toCharPtr(arena)); final deviceName = getDeviceName(); - _realmLib.realm_app_config_set_device_name(handle._pointer, deviceName.toCharPtr(arena)); + realmLib.realm_app_config_set_device_name(handle.pointer, deviceName.toCharPtr(arena)); final deviceVersion = getDeviceVersion(); - _realmLib.realm_app_config_set_device_version(handle._pointer, deviceVersion.toCharPtr(arena)); + realmLib.realm_app_config_set_device_version(handle.pointer, deviceVersion.toCharPtr(arena)); - _realmLib.realm_app_config_set_framework_name(handle._pointer, (isFlutterPlatform ? 'Flutter' : 'Dart VM').toCharPtr(arena)); - _realmLib.realm_app_config_set_framework_version(handle._pointer, Platform.version.toCharPtr(arena)); + realmLib.realm_app_config_set_framework_name(handle.pointer, (isFlutterPlatform ? 'Flutter' : 'Dart VM').toCharPtr(arena)); + realmLib.realm_app_config_set_framework_version(handle.pointer, Platform.version.toCharPtr(arena)); - _realmLib.realm_app_config_set_base_url(handle._pointer, configuration.baseUrl.toString().toCharPtr(arena)); + realmLib.realm_app_config_set_base_url(handle.pointer, configuration.baseUrl.toString().toCharPtr(arena)); - _realmLib.realm_app_config_set_default_request_timeout(handle._pointer, configuration.defaultRequestTimeout.inMilliseconds); + realmLib.realm_app_config_set_default_request_timeout(handle.pointer, configuration.defaultRequestTimeout.inMilliseconds); - _realmLib.realm_app_config_set_bundle_id(handle._pointer, getBundleId().toCharPtr(arena)); + realmLib.realm_app_config_set_bundle_id(handle.pointer, getBundleId().toCharPtr(arena)); _realmLib.realm_app_config_set_base_file_path(handle._pointer, configuration.baseFilePath.path.toCharPtr(arena)); _realmLib.realm_app_config_set_metadata_mode(handle._pointer, configuration.metadataPersistenceMode.index); @@ -1710,56 +1696,56 @@ class _RealmCore { } RealmAppCredentialsHandle createAppCredentialsAnonymous(bool reuseCredentials) { - return RealmAppCredentialsHandle._(_realmLib.realm_app_credentials_new_anonymous(reuseCredentials)); + return RealmAppCredentialsHandle._(realmLib.realm_app_credentials_new_anonymous(reuseCredentials)); } RealmAppCredentialsHandle createAppCredentialsEmailPassword(String email, String password) { return using((arena) { final emailPtr = email.toCharPtr(arena); final passwordPtr = password.toRealmString(arena); - return RealmAppCredentialsHandle._(_realmLib.realm_app_credentials_new_email_password(emailPtr, passwordPtr.ref)); + return RealmAppCredentialsHandle._(realmLib.realm_app_credentials_new_email_password(emailPtr, passwordPtr.ref)); }); } RealmAppCredentialsHandle createAppCredentialsJwt(String token) { return using((arena) { final tokenPtr = token.toCharPtr(arena); - return RealmAppCredentialsHandle._(_realmLib.realm_app_credentials_new_jwt(tokenPtr)); + return RealmAppCredentialsHandle._(realmLib.realm_app_credentials_new_jwt(tokenPtr)); }); } RealmAppCredentialsHandle createAppCredentialsApple(String idToken) { return using((arena) { final idTokenPtr = idToken.toCharPtr(arena); - return RealmAppCredentialsHandle._(_realmLib.realm_app_credentials_new_apple(idTokenPtr)); + return RealmAppCredentialsHandle._(realmLib.realm_app_credentials_new_apple(idTokenPtr)); }); } RealmAppCredentialsHandle createAppCredentialsFacebook(String accessToken) { return using((arena) { final accessTokenPtr = accessToken.toCharPtr(arena); - return RealmAppCredentialsHandle._(_realmLib.realm_app_credentials_new_facebook(accessTokenPtr)); + return RealmAppCredentialsHandle._(realmLib.realm_app_credentials_new_facebook(accessTokenPtr)); }); } RealmAppCredentialsHandle createAppCredentialsGoogleIdToken(String idToken) { return using((arena) { final idTokenPtr = idToken.toCharPtr(arena); - return RealmAppCredentialsHandle._(_realmLib.realm_app_credentials_new_google_id_token(idTokenPtr)); + return RealmAppCredentialsHandle._(realmLib.realm_app_credentials_new_google_id_token(idTokenPtr)); }); } RealmAppCredentialsHandle createAppCredentialsGoogleAuthCode(String authCode) { return using((arena) { final authCodePtr = authCode.toCharPtr(arena); - return RealmAppCredentialsHandle._(_realmLib.realm_app_credentials_new_google_auth_code(authCodePtr)); + return RealmAppCredentialsHandle._(realmLib.realm_app_credentials_new_google_auth_code(authCodePtr)); }); } RealmAppCredentialsHandle createAppCredentialsFunction(String payload) { return using((arena) { final payloadPtr = payload.toCharPtr(arena); - final credentialsPtr = invokeGetPointer(() => _realmLib.realm_app_credentials_new_function(payloadPtr)); + final credentialsPtr = invokeGetPointer(() => realmLib.realm_app_credentials_new_function(payloadPtr)); return RealmAppCredentialsHandle._(credentialsPtr); }); } @@ -1767,17 +1753,17 @@ class _RealmCore { RealmAppCredentialsHandle createAppCredentialsApiKey(String key) { return using((arena) { final keyPtr = key.toCharPtr(arena); - return RealmAppCredentialsHandle._(_realmLib.realm_app_credentials_new_api_key(keyPtr)); + return RealmAppCredentialsHandle._(realmLib.realm_app_credentials_new_api_key(keyPtr)); }); } RealmHttpTransportHandle _createHttpTransport(HttpClient httpClient) { final requestCallback = Pointer.fromFunction)>(_request_callback); - final requestCallbackUserdata = _realmLib.realm_dart_userdata_async_new(httpClient, requestCallback.cast(), scheduler.handle._pointer); - return RealmHttpTransportHandle._(_realmLib.realm_http_transport_new( - _realmLib.addresses.realm_dart_http_request_callback, + final requestCallbackUserdata = realmLib.realm_dart_userdata_async_new(httpClient, requestCallback.cast(), scheduler.handle.pointer); + return RealmHttpTransportHandle._(realmLib.realm_http_transport_new( + realmLib.addresses.realm_dart_http_request_callback, requestCallbackUserdata.cast(), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, )); } @@ -1900,7 +1886,7 @@ class _RealmCore { Realm.logger.log(LogLevel.error, "HTTP Transport: Exception executing ${method.name} $url: $ex"); responseRef.custom_status_code = _CustomErrorCode.unknown.code; } finally { - _realmLib.realm_http_transport_complete_request(request_context, response_pointer); + realmLib.realm_http_transport_complete_request(request_context, response_pointer); } }); } @@ -1923,11 +1909,11 @@ class _RealmCore { // call to createApp in the root isolate. if (_firstTime && _isRootIsolate) { _firstTime = false; - _realmLib.realm_clear_cached_apps(); + realmLib.realm_clear_cached_apps(); } final httpTransportHandle = _createHttpTransport(configuration.httpClient); final appConfigHandle = _createAppConfig(configuration, httpTransportHandle); - final realmAppPtr = invokeGetPointer(() => _realmLib.realm_app_create_cached(appConfigHandle._pointer)); + final realmAppPtr = invokeGetPointer(() => realmLib.realm_app_create_cached(appConfigHandle._pointer)); return AppHandle._(realmAppPtr); } @@ -1939,13 +1925,13 @@ class _RealmCore { AppHandle? getApp(String id, String? baseUrl) { return using((arena) { final out_app = arena>(); - invokeGetBool(() => _realmLib.realm_app_get_cached(id.toCharPtr(arena), baseUrl == null ? nullptr : baseUrl.toCharPtr(arena), out_app)); + invokeGetBool(() => realmLib.realm_app_get_cached(id.toCharPtr(arena), baseUrl == null ? nullptr : baseUrl.toCharPtr(arena), out_app)); return out_app.value == nullptr ? null : AppHandle._(out_app.value); }); } String appGetId(App app) { - return _realmLib.realm_app_get_app_id(app.handle._pointer).cast().toRealmDartString()!; + return realmLib.realm_app_get_app_id(app.handle.pointer).cast().toRealmDartString()!; } static void _app_user_completion_callback(Pointer userdata, Pointer user, Pointer error) { @@ -1956,7 +1942,7 @@ class _RealmCore { return; } - user = _realmLib.realm_clone(user.cast()).cast(); // take an extra reference to the user object + user = realmLib.realm_clone(user.cast()).cast(); // take an extra reference to the user object if (user == nullptr) { completer.completeError(RealmException("Error while cloning user object.")); return; @@ -1973,10 +1959,10 @@ class _RealmCore { Pointer, )>(_app_user_completion_callback); - final userdata = _realmLib.realm_dart_userdata_async_new( + final userdata = realmLib.realm_dart_userdata_async_new( completer, callback.cast(), - scheduler.handle._pointer, + scheduler.handle.pointer, ); return userdata.cast(); @@ -1987,12 +1973,12 @@ class _RealmCore { final userdata = _createAsyncUserCallbackUserdata(completer); invokeGetBool( - () => _realmLib.realm_app_log_in_with_credentials( - app.handle._pointer, - credentials.handle._pointer, - _realmLib.addresses.realm_dart_user_completion_callback, + () => realmLib.realm_app_log_in_with_credentials( + app.handle.pointer, + credentials.handle.pointer, + realmLib.addresses.realm_dart_user_completion_callback, userdata, - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, ), "Login failed"); @@ -2013,13 +1999,13 @@ class _RealmCore { Future appEmailPasswordRegisterUser(App app, String email, String password) { final completer = Completer(); using((arena) { - invokeGetBool(() => _realmLib.realm_app_email_password_provider_client_register_email( - app.handle._pointer, + invokeGetBool(() => realmLib.realm_app_email_password_provider_client_register_email( + app.handle.pointer, email.toCharPtr(arena), password.toRealmString(arena).ref, - _realmLib.addresses.realm_dart_void_completion_callback, + realmLib.addresses.realm_dart_void_completion_callback, _createAsyncCallbackUserdata(completer), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, )); }); return completer.future; @@ -2028,13 +2014,13 @@ class _RealmCore { Future emailPasswordConfirmUser(App app, String token, String tokenId) async { final completer = Completer(); using((arena) { - invokeGetBool(() => _realmLib.realm_app_email_password_provider_client_confirm_user( - app.handle._pointer, + invokeGetBool(() => realmLib.realm_app_email_password_provider_client_confirm_user( + app.handle.pointer, token.toCharPtr(arena), tokenId.toCharPtr(arena), - _realmLib.addresses.realm_dart_void_completion_callback, + realmLib.addresses.realm_dart_void_completion_callback, _createAsyncCallbackUserdata(completer), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, )); }); return await completer.future; @@ -2043,12 +2029,12 @@ class _RealmCore { Future emailPasswordResendUserConfirmation(App app, String email) { final completer = Completer(); using((arena) { - invokeGetBool(() => _realmLib.realm_app_email_password_provider_client_resend_confirmation_email( - app.handle._pointer, + invokeGetBool(() => realmLib.realm_app_email_password_provider_client_resend_confirmation_email( + app.handle.pointer, email.toCharPtr(arena), - _realmLib.addresses.realm_dart_void_completion_callback, + realmLib.addresses.realm_dart_void_completion_callback, _createAsyncCallbackUserdata(completer), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, )); }); return completer.future; @@ -2057,14 +2043,14 @@ class _RealmCore { Future emailPasswordCompleteResetPassword(App app, String password, String token, String tokenId) { final completer = Completer(); using((arena) { - invokeGetBool(() => _realmLib.realm_app_email_password_provider_client_reset_password( - app.handle._pointer, + invokeGetBool(() => realmLib.realm_app_email_password_provider_client_reset_password( + app.handle.pointer, password.toRealmString(arena).ref, token.toCharPtr(arena), tokenId.toCharPtr(arena), - _realmLib.addresses.realm_dart_void_completion_callback, + realmLib.addresses.realm_dart_void_completion_callback, _createAsyncCallbackUserdata(completer), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, )); }); return completer.future; @@ -2073,12 +2059,12 @@ class _RealmCore { Future emailPasswordResetPassword(App app, String email) { final completer = Completer(); using((arena) { - invokeGetBool(() => _realmLib.realm_app_email_password_provider_client_send_reset_password_email( - app.handle._pointer, + invokeGetBool(() => realmLib.realm_app_email_password_provider_client_send_reset_password_email( + app.handle.pointer, email.toCharPtr(arena), - _realmLib.addresses.realm_dart_void_completion_callback, + realmLib.addresses.realm_dart_void_completion_callback, _createAsyncCallbackUserdata(completer), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, )); }); return completer.future; @@ -2087,14 +2073,14 @@ class _RealmCore { Future emailPasswordCallResetPasswordFunction(App app, String email, String password, String? argsAsJSON) { final completer = Completer(); using((arena) { - invokeGetBool(() => _realmLib.realm_app_email_password_provider_client_call_reset_password_function( - app.handle._pointer, + invokeGetBool(() => realmLib.realm_app_email_password_provider_client_call_reset_password_function( + app.handle.pointer, email.toCharPtr(arena), password.toRealmString(arena).ref, argsAsJSON != null ? argsAsJSON.toCharPtr(arena) : nullptr, - _realmLib.addresses.realm_dart_void_completion_callback, + realmLib.addresses.realm_dart_void_completion_callback, _createAsyncCallbackUserdata(completer), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, )); }); return completer.future; @@ -2103,19 +2089,19 @@ class _RealmCore { Future emailPasswordRetryCustomConfirmationFunction(App app, String email) { final completer = Completer(); using((arena) { - invokeGetBool(() => _realmLib.realm_app_email_password_provider_client_retry_custom_confirmation( - app.handle._pointer, + invokeGetBool(() => realmLib.realm_app_email_password_provider_client_retry_custom_confirmation( + app.handle.pointer, email.toCharPtr(arena), - _realmLib.addresses.realm_dart_void_completion_callback, + realmLib.addresses.realm_dart_void_completion_callback, _createAsyncCallbackUserdata(completer), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, )); }); return completer.future; } UserHandle? getCurrentUser(AppHandle appHandle) { - final userPtr = _realmLib.realm_app_get_current_user(appHandle._pointer); + final userPtr = realmLib.realm_app_get_current_user(appHandle.pointer); if (userPtr == nullptr) { return null; } @@ -2126,21 +2112,21 @@ class _RealmCore { final completer = Completer(); if (user == null) { invokeGetBool( - () => _realmLib.realm_app_log_out_current_user( - application.handle._pointer, - _realmLib.addresses.realm_dart_void_completion_callback, + () => realmLib.realm_app_log_out_current_user( + application.handle.pointer, + realmLib.addresses.realm_dart_void_completion_callback, _createAsyncCallbackUserdata(completer), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, ), "Logout failed"); } else { invokeGetBool( - () => _realmLib.realm_app_log_out( - application.handle._pointer, - user.handle._pointer, - _realmLib.addresses.realm_dart_void_completion_callback, + () => realmLib.realm_app_log_out( + application.handle.pointer, + user.handle.pointer, + realmLib.addresses.realm_dart_void_completion_callback, _createAsyncCallbackUserdata(completer), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, ), "Logout failed"); } @@ -2148,7 +2134,7 @@ class _RealmCore { } void clearCachedApps() { - _realmLib.realm_clear_cached_apps(); + realmLib.realm_clear_cached_apps(); } List getUsers(App app) { @@ -2160,7 +2146,7 @@ class _RealmCore { List _getUsers(App app, Arena arena, {int expectedSize = 2}) { final actualCount = arena(); final usersPtr = arena>(expectedSize); - invokeGetBool(() => _realmLib.realm_app_get_all_users(app.handle._pointer, usersPtr, expectedSize, actualCount)); + invokeGetBool(() => realmLib.realm_app_get_all_users(app.handle.pointer, usersPtr, expectedSize, actualCount)); if (expectedSize < actualCount.value) { // The supplied array was too small - resize it @@ -2179,12 +2165,12 @@ class _RealmCore { Future removeUser(App app, User user) { final completer = Completer(); invokeGetBool( - () => _realmLib.realm_app_remove_user( - app.handle._pointer, - user.handle._pointer, - _realmLib.addresses.realm_dart_void_completion_callback, + () => realmLib.realm_app_remove_user( + app.handle.pointer, + user.handle.pointer, + realmLib.addresses.realm_dart_void_completion_callback, _createAsyncCallbackUserdata(completer), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, ), "Remove user failed"); return completer.future; @@ -2193,22 +2179,22 @@ class _RealmCore { void switchUser(App application, User user) { return using((arena) { invokeGetBool( - () => _realmLib.realm_app_switch_user( - application.handle._pointer, - user.handle._pointer, + () => realmLib.realm_app_switch_user( + application.handle.pointer, + user.handle.pointer, ), "Switch user failed"); }); } void reconnect(App application) { - _realmLib.realm_app_sync_client_reconnect( - application.handle._pointer, + realmLib.realm_app_sync_client_reconnect( + application.handle.pointer, ); } String getBaseUrl(App app) { - final customDataPtr = _realmLib.realm_app_get_base_url(app.handle._pointer); + final customDataPtr = realmLib.realm_app_get_base_url(app.handle.pointer); return customDataPtr.cast().toRealmDartString(freeRealmMemory: true)!; } @@ -2216,12 +2202,12 @@ class _RealmCore { final completer = Completer(); using((arena) { invokeGetBool( - () => _realmLib.realm_app_update_base_url( + () => realmLib.realm_app_update_base_url( app.handle._pointer, baseUrl?.toString().toCharPtr(arena) ?? nullptr, - _realmLib.addresses.realm_dart_void_completion_callback, + realmLib.addresses.realm_dart_void_completion_callback, _createAsyncCallbackUserdata(completer), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, ), "Update base URL failed"); }); @@ -2229,19 +2215,19 @@ class _RealmCore { } String? userGetCustomData(User user) { - final customDataPtr = _realmLib.realm_user_get_custom_data(user.handle._pointer); + final customDataPtr = realmLib.realm_user_get_custom_data(user.handle.pointer); return customDataPtr.cast().toRealmDartString(freeRealmMemory: true, treatEmptyAsNull: true); } Future userRefreshCustomData(App app, User user) { final completer = Completer(); invokeGetBool( - () => _realmLib.realm_app_refresh_custom_data( - app.handle._pointer, - user.handle._pointer, - _realmLib.addresses.realm_dart_void_completion_callback, + () => realmLib.realm_app_refresh_custom_data( + app.handle.pointer, + user.handle.pointer, + realmLib.addresses.realm_dart_void_completion_callback, _createAsyncCallbackUserdata(completer), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, ), "Refresh custom data failed"); return completer.future; @@ -2250,31 +2236,31 @@ class _RealmCore { Future userLinkCredentials(App app, User user, Credentials credentials) { final completer = Completer(); invokeGetBool( - () => _realmLib.realm_app_link_user( - app.handle._pointer, - user.handle._pointer, - credentials.handle._pointer, - _realmLib.addresses.realm_dart_user_completion_callback, + () => realmLib.realm_app_link_user( + app.handle.pointer, + user.handle.pointer, + credentials.handle.pointer, + realmLib.addresses.realm_dart_user_completion_callback, _createAsyncUserCallbackUserdata(completer), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, ), "Link credentials failed"); return completer.future; } UserState userGetState(User user) { - final nativeUserState = _realmLib.realm_user_get_state(user.handle._pointer); + final nativeUserState = realmLib.realm_user_get_state(user.handle.pointer); return UserState.values.fromIndex(nativeUserState); } String userGetId(User user) { - final idPtr = invokeGetPointer(() => _realmLib.realm_user_get_identity(user.handle._pointer), "Error while getting user id"); + final idPtr = invokeGetPointer(() => realmLib.realm_user_get_identity(user.handle.pointer), "Error while getting user id"); final userId = idPtr.cast().toDartString(); return userId; } AppHandle userGetApp(UserHandle userHandle) { - final appPtr = _realmLib.realm_user_get_app(userHandle._pointer); + final appPtr = realmLib.realm_user_get_app(userHandle.pointer); if (appPtr == nullptr) { throw RealmException('User does not have an associated app. This is likely due to the user being logged out.'); } @@ -2291,7 +2277,7 @@ class _RealmCore { List _userGetIdentities(User user, Arena arena, {int expectedSize = 2}) { final actualCount = arena(); final identitiesPtr = arena(expectedSize); - invokeGetBool(() => _realmLib.realm_user_get_all_identities(user.handle._pointer, identitiesPtr, expectedSize, actualCount)); + invokeGetBool(() => realmLib.realm_user_get_all_identities(user.handle.pointer, identitiesPtr, expectedSize, actualCount)); if (expectedSize < actualCount.value) { // The supplied array was too small - resize it @@ -2311,56 +2297,56 @@ class _RealmCore { } Future userLogOut(User user) { - invokeGetBool(() => _realmLib.realm_user_log_out(user.handle._pointer), "Logout failed"); + invokeGetBool(() => realmLib.realm_user_log_out(user.handle.pointer), "Logout failed"); return Future.value(); } String? userGetDeviceId(User user) { - final deviceId = invokeGetPointer(() => _realmLib.realm_user_get_device_id(user.handle._pointer)); + final deviceId = invokeGetPointer(() => realmLib.realm_user_get_device_id(user.handle.pointer)); return deviceId.cast().toRealmDartString(treatEmptyAsNull: true, freeRealmMemory: true); } AuthProviderType userGetCredentialsProviderType(Credentials credentials) { - final provider = _realmLib.realm_auth_credentials_get_provider(credentials.handle._pointer); + final provider = realmLib.realm_auth_credentials_get_provider(credentials.handle.pointer); return AuthProviderTypeInternal.getByValue(provider); } UserProfile userGetProfileData(User user) { - final data = invokeGetPointer(() => _realmLib.realm_user_get_profile_data(user.handle._pointer)); + final data = invokeGetPointer(() => realmLib.realm_user_get_profile_data(user.handle.pointer)); final dynamic profileData = jsonDecode(data.cast().toRealmDartString(freeRealmMemory: true)!); return UserProfile(profileData as Map); } String userGetRefreshToken(User user) { - final token = invokeGetPointer(() => _realmLib.realm_user_get_refresh_token(user.handle._pointer)); + final token = invokeGetPointer(() => realmLib.realm_user_get_refresh_token(user.handle.pointer)); return token.cast().toRealmDartString(freeRealmMemory: true)!; } String userGetAccessToken(User user) { - final token = invokeGetPointer(() => _realmLib.realm_user_get_access_token(user.handle._pointer)); + final token = invokeGetPointer(() => realmLib.realm_user_get_access_token(user.handle.pointer)); return token.cast().toRealmDartString(freeRealmMemory: true)!; } SessionHandle realmGetSession(Realm realm) { - return SessionHandle._(invokeGetPointer(() => _realmLib.realm_sync_session_get(realm.handle._pointer)), realm.handle); + return SessionHandle._(invokeGetPointer(() => realmLib.realm_sync_session_get(realm.handle.pointer)), realm.handle); } String sessionGetPath(Session session) { - return _realmLib.realm_sync_session_get_file_path(session.handle._pointer).cast().toRealmDartString()!; + return realmLib.realm_sync_session_get_file_path(session.handle.pointer).cast().toRealmDartString()!; } SessionState sessionGetState(Session session) { - final value = _realmLib.realm_sync_session_get_state(session.handle._pointer); + final value = realmLib.realm_sync_session_get_state(session.handle.pointer); return _convertCoreSessionState(value); } ConnectionState sessionGetConnectionState(Session session) { - final value = _realmLib.realm_sync_session_get_connection_state(session.handle._pointer); + final value = realmLib.realm_sync_session_get_connection_state(session.handle.pointer); return ConnectionState.values[value]; } UserHandle sessionGetUser(Session session) { - return UserHandle._(_realmLib.realm_sync_session_get_user(session.handle._pointer)); + return UserHandle._(realmLib.realm_sync_session_get_user(session.handle.pointer)); } SessionState _convertCoreSessionState(int value) { @@ -2378,25 +2364,25 @@ class _RealmCore { } void sessionPause(Session session) { - _realmLib.realm_sync_session_pause(session.handle._pointer); + realmLib.realm_sync_session_pause(session.handle.pointer); } void sessionResume(Session session) { - _realmLib.realm_sync_session_resume(session.handle._pointer); + realmLib.realm_sync_session_resume(session.handle.pointer); } RealmSyncSessionConnectionStateNotificationTokenHandle sessionRegisterProgressNotifier( Session session, ProgressDirection direction, ProgressMode mode, SessionProgressNotificationsController controller) { final isStreaming = mode == ProgressMode.reportIndefinitely; final callback = Pointer.fromFunction(_syncProgressCallback); - final userdata = _realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle._pointer); - final tokenPtr = invokeGetPointer(() => _realmLib.realm_sync_session_register_progress_notifier( - session.handle._pointer, - _realmLib.addresses.realm_dart_sync_progress_callback, + final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); + final tokenPtr = invokeGetPointer(() => realmLib.realm_sync_session_register_progress_notifier( + session.handle.pointer, + realmLib.addresses.realm_dart_sync_progress_callback, direction.index, isStreaming, userdata.cast(), - _realmLib.addresses.realm_dart_userdata_async_free)); + realmLib.addresses.realm_dart_userdata_async_free)); return RealmSyncSessionConnectionStateNotificationTokenHandle._(tokenPtr); } @@ -2408,12 +2394,12 @@ class _RealmCore { RealmSyncSessionConnectionStateNotificationTokenHandle sessionRegisterConnectionStateNotifier(Session session, SessionConnectionStateController controller) { final callback = Pointer.fromFunction(_onConnectionStateChange); - final userdata = _realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle._pointer); - final notification_token = _realmLib.realm_sync_session_register_connection_state_change_callback( - session.handle._pointer, - _realmLib.addresses.realm_dart_sync_connection_state_changed_callback, + final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); + final notification_token = realmLib.realm_sync_session_register_connection_state_change_callback( + session.handle.pointer, + realmLib.addresses.realm_dart_sync_connection_state_changed_callback, userdata.cast(), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, ); return RealmSyncSessionConnectionStateNotificationTokenHandle._(notification_token); } @@ -2428,9 +2414,9 @@ class _RealmCore { final completer = CancellableCompleter(cancellationToken); if (!completer.isCancelled) { final callback = Pointer.fromFunction)>(_sessionWaitCompletionCallback); - final userdata = _realmLib.realm_dart_userdata_async_new(completer, callback.cast(), scheduler.handle._pointer); - _realmLib.realm_sync_session_wait_for_upload_completion(session.handle._pointer, _realmLib.addresses.realm_dart_sync_wait_for_completion_callback, - userdata.cast(), _realmLib.addresses.realm_dart_userdata_async_free); + final userdata = realmLib.realm_dart_userdata_async_new(completer, callback.cast(), scheduler.handle.pointer); + realmLib.realm_sync_session_wait_for_upload_completion(session.handle.pointer, realmLib.addresses.realm_dart_sync_wait_for_completion_callback, + userdata.cast(), realmLib.addresses.realm_dart_userdata_async_free); } return completer.future; } @@ -2439,9 +2425,9 @@ class _RealmCore { final completer = CancellableCompleter(cancellationToken); if (!completer.isCancelled) { final callback = Pointer.fromFunction)>(_sessionWaitCompletionCallback); - final userdata = _realmLib.realm_dart_userdata_async_new(completer, callback.cast(), scheduler.handle._pointer); - _realmLib.realm_sync_session_wait_for_download_completion(session.handle._pointer, _realmLib.addresses.realm_dart_sync_wait_for_completion_callback, - userdata.cast(), _realmLib.addresses.realm_dart_userdata_async_free); + final userdata = realmLib.realm_dart_userdata_async_new(completer, callback.cast(), scheduler.handle.pointer); + realmLib.realm_sync_session_wait_for_download_completion(session.handle.pointer, realmLib.addresses.realm_dart_sync_wait_for_completion_callback, + userdata.cast(), realmLib.addresses.realm_dart_userdata_async_free); } return completer.future; } @@ -2473,7 +2459,7 @@ class _RealmCore { } if (Platform.isAndroid) { - return _realmLib.realm_dart_get_bundle_id().cast().toDartString(); + return realmLib.realm_dart_get_bundle_id().cast().toDartString(); } final getBundleIdFunc = _pluginLib.lookupFunction Function(), Pointer Function()>("realm_dart_get_bundle_id"); @@ -2536,35 +2522,35 @@ class _RealmCore { Future deleteUser(App app, User user) { final completer = Completer(); invokeGetBool( - () => _realmLib.realm_app_delete_user( - app.handle._pointer, - user.handle._pointer, - _realmLib.addresses.realm_dart_void_completion_callback, + () => realmLib.realm_app_delete_user( + app.handle.pointer, + user.handle.pointer, + realmLib.addresses.realm_dart_void_completion_callback, _createAsyncCallbackUserdata(completer), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, ), "Delete user failed"); return completer.future; } bool isFrozen(Realm realm) { - return _realmLib.realm_is_frozen(realm.handle._pointer.cast()); + return realmLib.realm_is_frozen(realm.handle.pointer.cast()); } RealmHandle freeze(Realm realm) { - final ptr = invokeGetPointer(() => _realmLib.realm_freeze(realm.handle._pointer)); + final ptr = invokeGetPointer(() => realmLib.realm_freeze(realm.handle.pointer)); return RealmHandle._(ptr); } RealmResultsHandle resolveResults(RealmResults realmResults, Realm frozenRealm) { - final ptr = invokeGetPointer(() => _realmLib.realm_results_resolve_in(realmResults.handle._pointer, frozenRealm.handle._pointer)); + final ptr = invokeGetPointer(() => realmLib.realm_results_resolve_in(realmResults.handle.pointer, frozenRealm.handle.pointer)); return RealmResultsHandle._(ptr, frozenRealm.handle); } RealmObjectHandle? resolveObject(RealmObjectBase object, Realm frozenRealm) { return using((Arena arena) { final resultPtr = arena>(); - invokeGetBool(() => _realmLib.realm_object_resolve_in(object.handle._pointer, frozenRealm.handle._pointer, resultPtr)); + invokeGetBool(() => realmLib.realm_object_resolve_in(object.handle.pointer, frozenRealm.handle.pointer, resultPtr)); return resultPtr == nullptr ? null : RealmObjectHandle._(resultPtr.value, frozenRealm.handle); }); } @@ -2572,7 +2558,7 @@ class _RealmCore { RealmListHandle? resolveList(ManagedRealmList list, Realm frozenRealm) { return using((Arena arena) { final resultPtr = arena>(); - invokeGetBool(() => _realmLib.realm_list_resolve_in(list.handle._pointer, frozenRealm.handle._pointer, resultPtr)); + invokeGetBool(() => realmLib.realm_list_resolve_in(list.handle.pointer, frozenRealm.handle.pointer, resultPtr)); return resultPtr == nullptr ? null : RealmListHandle._(resultPtr.value, frozenRealm.handle); }); } @@ -2580,7 +2566,7 @@ class _RealmCore { RealmSetHandle? resolveSet(ManagedRealmSet set, Realm frozenRealm) { return using((Arena arena) { final resultPtr = arena>(); - invokeGetBool(() => _realmLib.realm_set_resolve_in(set.handle._pointer, frozenRealm.handle._pointer, resultPtr)); + invokeGetBool(() => realmLib.realm_set_resolve_in(set.handle.pointer, frozenRealm.handle.pointer, resultPtr)); return resultPtr == nullptr ? null : RealmSetHandle._(resultPtr.value, frozenRealm.handle); }); } @@ -2588,7 +2574,7 @@ class _RealmCore { RealmMapHandle? resolveMap(ManagedRealmMap map, Realm frozenRealm) { return using((Arena arena) { final resultPtr = arena>(); - invokeGetBool(() => _realmLib.realm_dictionary_resolve_in(map.handle._pointer, frozenRealm.handle._pointer, resultPtr)); + invokeGetBool(() => realmLib.realm_dictionary_resolve_in(map.handle.pointer, frozenRealm.handle.pointer, resultPtr)); return resultPtr == nullptr ? null : RealmMapHandle._(resultPtr.value, frozenRealm.handle); }); } @@ -2622,13 +2608,13 @@ class _RealmCore { return using((Arena arena) { final namePtr = name.toCharPtr(arena); final completer = Completer(); - invokeGetBool(() => _realmLib.realm_app_user_apikey_provider_client_create_apikey( - user.app.handle._pointer, - user.handle._pointer, + invokeGetBool(() => realmLib.realm_app_user_apikey_provider_client_create_apikey( + user.app.handle.pointer, + user.handle.pointer, namePtr, - _realmLib.addresses.realm_dart_apikey_callback, + realmLib.addresses.realm_dart_apikey_callback, _createAsyncApikeyCallbackUserdata(completer), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, )); return completer.future; @@ -2639,13 +2625,13 @@ class _RealmCore { return using((Arena arena) { final completer = Completer(); final native_id = id.toNative(arena); - invokeGetBool(() => _realmLib.realm_app_user_apikey_provider_client_fetch_apikey( - user.app.handle._pointer, - user.handle._pointer, + invokeGetBool(() => realmLib.realm_app_user_apikey_provider_client_fetch_apikey( + user.app.handle.pointer, + user.handle.pointer, native_id.ref, - _realmLib.addresses.realm_dart_apikey_callback, + realmLib.addresses.realm_dart_apikey_callback, _createAsyncApikeyCallbackUserdata(completer), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, )); return completer.future; @@ -2655,12 +2641,12 @@ class _RealmCore { Future> fetchAllApiKeys(User user) { return using((Arena arena) { final completer = Completer>(); - invokeGetBool(() => _realmLib.realm_app_user_apikey_provider_client_fetch_apikeys( - user.app.handle._pointer, - user.handle._pointer, - _realmLib.addresses.realm_dart_apikey_list_callback, + invokeGetBool(() => realmLib.realm_app_user_apikey_provider_client_fetch_apikeys( + user.app.handle.pointer, + user.handle.pointer, + realmLib.addresses.realm_dart_apikey_list_callback, _createAsyncApikeyListCallbackUserdata(completer), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, )); return completer.future; @@ -2671,13 +2657,13 @@ class _RealmCore { return using((Arena arena) { final completer = Completer(); final native_id = id.toNative(arena); - invokeGetBool(() => _realmLib.realm_app_user_apikey_provider_client_delete_apikey( - user.app.handle._pointer, - user.handle._pointer, + invokeGetBool(() => realmLib.realm_app_user_apikey_provider_client_delete_apikey( + user.app.handle.pointer, + user.handle.pointer, native_id.ref, - _realmLib.addresses.realm_dart_void_completion_callback, + realmLib.addresses.realm_dart_void_completion_callback, _createAsyncCallbackUserdata(completer), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, )); return completer.future; @@ -2691,10 +2677,10 @@ class _RealmCore { Pointer, )>(_void_completion_callback); - final userdata = _realmLib.realm_dart_userdata_async_new( + final userdata = realmLib.realm_dart_userdata_async_new( completer, callback.cast(), - scheduler.handle._pointer, + scheduler.handle.pointer, ); return userdata.cast(); @@ -2708,10 +2694,10 @@ class _RealmCore { Pointer, )>(_app_api_key_completion_callback); - final userdata = _realmLib.realm_dart_userdata_async_new( + final userdata = realmLib.realm_dart_userdata_async_new( completer, callback.cast(), - scheduler.handle._pointer, + scheduler.handle.pointer, ); return userdata.cast(); @@ -2726,10 +2712,10 @@ class _RealmCore { Pointer, )>(_app_api_key_array_completion_callback); - final userdata = _realmLib.realm_dart_userdata_async_new( + final userdata = realmLib.realm_dart_userdata_async_new( completer, callback.cast(), - scheduler.handle._pointer, + scheduler.handle.pointer, ); return userdata.cast(); @@ -2740,13 +2726,13 @@ class _RealmCore { final completer = Completer(); final native_id = objectId.toNative(arena); - invokeGetBool(() => _realmLib.realm_app_user_apikey_provider_client_disable_apikey( - user.app.handle._pointer, - user.handle._pointer, + invokeGetBool(() => realmLib.realm_app_user_apikey_provider_client_disable_apikey( + user.app.handle.pointer, + user.handle.pointer, native_id.ref, - _realmLib.addresses.realm_dart_void_completion_callback, + realmLib.addresses.realm_dart_void_completion_callback, _createAsyncCallbackUserdata(completer), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, )); return completer.future; @@ -2757,13 +2743,13 @@ class _RealmCore { return using((Arena arena) { final completer = Completer(); final native_id = objectId.toNative(arena); - invokeGetBool(() => _realmLib.realm_app_user_apikey_provider_client_enable_apikey( - user.app.handle._pointer, - user.handle._pointer, + invokeGetBool(() => realmLib.realm_app_user_apikey_provider_client_enable_apikey( + user.app.handle.pointer, + user.handle.pointer, native_id.ref, - _realmLib.addresses.realm_dart_void_completion_callback, + realmLib.addresses.realm_dart_void_completion_callback, _createAsyncCallbackUserdata(completer), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, )); return completer.future; @@ -2790,10 +2776,10 @@ class _RealmCore { Pointer, )>(_call_app_function_callback); - final userdata = _realmLib.realm_dart_userdata_async_new( + final userdata = realmLib.realm_dart_userdata_async_new( completer, callback.cast(), - scheduler.handle._pointer, + scheduler.handle.pointer, ); return userdata.cast(); @@ -2802,15 +2788,15 @@ class _RealmCore { Future callAppFunction(App app, User user, String functionName, String? argsAsJSON) { return using((arena) { final completer = Completer(); - invokeGetBool(() => _realmLib.realm_app_call_function( - app.handle._pointer, - user.handle._pointer, + invokeGetBool(() => realmLib.realm_app_call_function( + app.handle.pointer, + user.handle.pointer, functionName.toCharPtr(arena), argsAsJSON?.toCharPtr(arena) ?? nullptr, nullptr, - _realmLib.addresses.realm_dart_return_string_callback, + realmLib.addresses.realm_dart_return_string_callback, _createAsyncFunctionCallbackUserdata(completer), - _realmLib.addresses.realm_dart_userdata_async_free, + realmLib.addresses.realm_dart_userdata_async_free, )); return completer.future; }); @@ -2819,7 +2805,7 @@ class _RealmCore { bool compact(Realm realm) { return using((arena) { final out_did_compact = arena(); - invokeGetBool(() => _realmLib.realm_compact(realm.handle._pointer, out_did_compact)); + invokeGetBool(() => realmLib.realm_compact(realm.handle.pointer, out_did_compact)); return out_did_compact.value; }); } @@ -2827,7 +2813,7 @@ class _RealmCore { bool immediatelyRunFileActions(App app, String realmPath) { return using((arena) { final out_did_run = arena(); - invokeGetBool(() => _realmLib.realm_sync_immediately_run_file_actions(app.handle._pointer, realmPath.toCharPtr(arena), out_did_run), + invokeGetBool(() => realmLib.realm_sync_immediately_run_file_actions(app.handle.pointer, realmPath.toCharPtr(arena), out_did_run), "An error occurred while resetting the Realm. Check if the file is in use: '$realmPath'"); return out_did_run.value; }); @@ -2835,7 +2821,7 @@ class _RealmCore { void writeCopy(Realm realm, Configuration config) { final configHandle = _createConfig(config); - invokeGetBool(() => _realmLib.realm_convert_with_config(realm.handle._pointer, configHandle._pointer, false)); + invokeGetBool(() => realmLib.realm_convert_with_config(realm.handle.pointer, configHandle.pointer, false)); } void _createCollection(Realm realm, RealmValue value, Pointer Function() createList, Pointer Function() createMap) { @@ -2876,133 +2862,22 @@ class _RealmCore { } } - void setLogLevel(LogLevel level, {required LogCategory category}) { - using((arena) { - _realmLib.realm_set_log_level_category(category.toString().toCharPtr(arena), level.index); - }); - } - - List getAllCategoryNames() { - return using((arena) { - final count = _realmLib.realm_get_category_names(0, nullptr); - final out_values = arena>(count); - _realmLib.realm_get_category_names(count, out_values); - return [for (int i = 0; i < count; i++) out_values[i].cast().toDartString()]; - }); - } -} - -// Flag to enable trace on finalization. -// -// Be aware that the trace is likely late, and it might in rare case be missing, -// as there are no absolute guarantees with Finalizer. -// -// It is often beneficial to also instrument the native realm_release to -// print the address released to get the exact time. -const _enableFinalizerTrace = false; - -// Level used for finalization trace, if enabled. -const _finalizerTraceLevel = LogLevel.trace; - -void _traceFinalization(Object o) { - Realm.logger.log(_finalizerTraceLevel, 'Finalizing: $o'); -} - -final _debugFinalizer = Finalizer(_traceFinalization); - -void _setupFinalizationTrace(Object value, Object finalizationToken) { - _debugFinalizer.attach(value, finalizationToken, detach: value); -} - -void _tearDownFinalizationTrace(Object value, Object finalizationToken) { - _debugFinalizer.detach(value); - _traceFinalization(finalizationToken); -} - -abstract class HandleBase implements Finalizable { - late Pointer _finalizableHandle; - Pointer _pointer; - bool get released => _pointer == nullptr; - final bool isUnowned; - - @pragma('vm:never-inline') - void keepAlive() {} - - HandleBase(this._pointer, int size) : isUnowned = false { - _finalizableHandle = _realmLib.realm_attach_finalizer(this, _pointer.cast(), size); - - if (_enableFinalizerTrace) { - _setupFinalizationTrace(this, _pointer); - } - } - - HandleBase.unowned(this._pointer) : isUnowned = true; - - @override - String toString() => "${_pointer.toString()} value=${_pointer.cast().value}${isUnowned ? ' (unowned)' : ''}"; - - /// @nodoc - /// A method that will be invoked just before the handle is released. Allows to cleanup - /// any custom data that inheritors are storing. - void _releaseCore() {} - - void release() { - if (released) { - return; - } - - _releaseCore(); - - if (!isUnowned) { - _realmLib.realm_detach_finalizer(_finalizableHandle, this); - - _realmLib.realm_release(_pointer.cast()); - } - - _pointer = nullptr; - - if (_enableFinalizerTrace) { - _tearDownFinalizationTrace(this, _pointer); - } - } -} - -class FinalizationToken { - final WeakReference root; - final int id; - - FinalizationToken(RealmHandle handle, this.id) : root = WeakReference(handle); +void setLogLevel(LogLevel level, {required LogCategory category}) { +using((arena) { +_realmLib.realm_set_log_level_category(category.toString().toCharPtr(arena), level.index); +}); } -// This finalizer is intended to prevent the list of children in the RealmHandle -// from growing endlessly. It's not intended to replace the native finalizer which -// will free the actual resources owned by the handle. -final _rootedHandleFinalizer = Finalizer((token) { - token.root.target?.removeChild(token.id); +List getAllCategoryNames() { +return using((arena) { +final count = _realmLib.realm_get_category_names(0, nullptr); +final out_values = arena>(count); +_realmLib.realm_get_category_names(count, out_values); +return [for (int i = 0; i < count; i++) out_values[i].cast().toDartString()]; }); - -abstract class RootedHandleBase extends HandleBase { - final RealmHandle _root; - int? _id; - - bool get shouldRoot => _root.isUnowned; - - RootedHandleBase(this._root, Pointer pointer, int size) : super(pointer, size) { - if (shouldRoot) { - _id = _root.addChild(this); - } - } - - @override - void _releaseCore() { - if (_id != null) { - _root.removeChild(_id!); - } - } +} } -abstract class CollectionHandleBase extends RootedHandleBase { - CollectionHandleBase(super.root, super.pointer, super.size); } class SchemaHandle extends HandleBase { @@ -3027,7 +2902,7 @@ class RealmHandle extends HandleBase { int addChild(RootedHandleBase child) { final id = _counter++; _children[id] = WeakReference(child); - _rootedHandleFinalizer.attach(this, FinalizationToken(this, id), detach: this); + rootedHandleFinalizer.attach(this, FinalizationToken(this, id), detach: this); return id; } @@ -3036,7 +2911,7 @@ class RealmHandle extends HandleBase { if (child != null) { final target = child.target; if (target != null) { - _rootedHandleFinalizer.detach(target); + rootedHandleFinalizer.detach(target); } } } @@ -3061,18 +2936,18 @@ class RealmObjectHandle extends RootedHandleBase { factory RealmObjectHandle.createWithPrimaryKey(RealmHandle realm, int classKey, Object? primaryKey) { return using((Arena arena) { final realm_value = _toRealmValue(primaryKey, arena); - final realmPtr = invokeGetPointer(() => _realmLib.realm_object_create_with_primary_key(realm._pointer, classKey, realm_value.ref)); + final realmPtr = invokeGetPointer(() => realmLib.realm_object_create_with_primary_key(realm.pointer, classKey, realm_value.ref)); return RealmObjectHandle._(realmPtr, realm); }); } factory RealmObjectHandle.create(RealmHandle realm, int classKey) { - final realmPtr = invokeGetPointer(() => _realmLib.realm_object_create(realm._pointer, classKey)); + final realmPtr = invokeGetPointer(() => realmLib.realm_object_create(realm.pointer, classKey)); return RealmObjectHandle._(realmPtr, realm); } factory RealmObjectHandle.createEmbedded(RealmObjectHandle parent, int propertyKey) { - final objectPtr = invokeGetPointer(() => _realmLib.realm_set_embedded(parent._pointer, propertyKey)); + final objectPtr = invokeGetPointer(() => realmLib.realm_set_embedded(parent.pointer, propertyKey)); return RealmObjectHandle._(objectPtr, parent._root); } @@ -3080,8 +2955,8 @@ class RealmObjectHandle extends RootedHandleBase { return using((Arena arena) { final realm_value = _toRealmValue(primaryKey, arena); final didCreate = arena(); - final realmPtr = invokeGetPointer(() => _realmLib.realm_object_get_or_create_with_primary_key( - realm._pointer, + final realmPtr = invokeGetPointer(() => realmLib.realm_object_get_or_create_with_primary_key( + realm.pointer, classKey, realm_value.ref, didCreate, @@ -3179,8 +3054,6 @@ class RealmAsyncOpenTaskProgressNotificationTokenHandle extends HandleBase pointer) : super(pointer, 40); } - - class SessionHandle extends RootedHandleBase { @override bool get shouldRoot => true; @@ -3371,7 +3244,7 @@ extension on realm_value_t { return DateTime.fromMicrosecondsSinceEpoch(seconds * _microsecondsPerSecond + nanoseconds ~/ _nanosecondsPerMicrosecond, isUtc: true); case realm_value_type.RLM_TYPE_DECIMAL128: var decimal = values.decimal128; // NOTE: Does not copy the struct! - decimal = _realmLib.realm_dart_decimal128_copy(decimal); // This is a workaround to that + decimal = realmLib.realm_dart_decimal128_copy(decimal); // This is a workaround to that return Decimal128Internal.fromNative(decimal); case realm_value_type.RLM_TYPE_OBJECT_ID: return ObjectId.fromBytes(values.object_id.bytes.toList(12)); @@ -3436,7 +3309,7 @@ extension on Pointer { T toObject() { assert(this != nullptr, "Pointer is null"); - Object object = _realmLib.realm_dart_persistent_handle_to_object(this); + Object object = realmLib.realm_dart_persistent_handle_to_object(this); assert(object is T, "$T expected"); return object as T; @@ -3445,7 +3318,7 @@ extension on Pointer { Object? toUserCodeError() { if (this != nullptr) { final result = toObject(); - _realmLib.realm_dart_delete_persistent_handle(this); + realmLib.realm_dart_delete_persistent_handle(this); return result; } @@ -3468,7 +3341,7 @@ extension on Pointer { return result; } finally { if (freeRealmMemory) { - _realmLib.realm_free(cast()); + realmLib.realm_free(cast()); } } } @@ -3537,7 +3410,7 @@ extension on Pointer { extension on Object { Pointer toPersistentHandle() { - return _realmLib.realm_dart_object_to_persistent_handle(this); + return realmLib.realm_dart_object_to_persistent_handle(this); } } diff --git a/packages/realm_dart/lib/src/native/realm_library.dart b/packages/realm_dart/lib/src/native/realm_library.dart new file mode 100644 index 000000000..f4c388176 --- /dev/null +++ b/packages/realm_dart/lib/src/native/realm_library.dart @@ -0,0 +1,21 @@ +// This variable allows access to realm native library even before RealmCore is created. For Decimal128 for example +import 'package:ffi/ffi.dart'; +import 'package:realm_common/realm_common.dart'; +import 'package:realm_dart/src/init.dart'; +import 'package:realm_dart/src/native/realm_bindings.dart'; + +const bugInTheSdkMessage = "This is likely a bug in the Realm SDK - please file an issue at https://github.com/realm/realm-dart/issues"; + +// stamped into the library by the build system (see prepare-release.yml) +const libraryVersion = '2.3.0'; + +final realmLib = () { + final result = RealmLibrary(initRealm()); + final nativeLibraryVersion = result.realm_dart_library_version().cast().toDartString(); + if (libraryVersion != nativeLibraryVersion) { + final additionMessage = + isFlutterPlatform ? bugInTheSdkMessage : "Did you forget to run `dart run realm_dart install` after upgrading the realm_dart package?"; + throw RealmError('Realm SDK package version does not match the native library version ($libraryVersion != $nativeLibraryVersion). $additionMessage'); + } + return result; +}(); diff --git a/packages/realm_dart/lib/src/native/rooted_handle.dart b/packages/realm_dart/lib/src/native/rooted_handle.dart new file mode 100644 index 000000000..1dd2e2bf5 --- /dev/null +++ b/packages/realm_dart/lib/src/native/rooted_handle.dart @@ -0,0 +1,39 @@ +part of 'realm_core.dart'; + +class FinalizationToken { + final WeakReference root; + final int id; + + FinalizationToken(RealmHandle handle, this.id) : root = WeakReference(handle); +} + +// This finalizer is intended to prevent the list of children in the RealmHandle +// from growing endlessly. It's not intended to replace the native finalizer which +// will free the actual resources owned by the handle. +final rootedHandleFinalizer = Finalizer((token) { + token.root.target?.removeChild(token.id); +}); + +abstract class RootedHandleBase extends HandleBase { + final RealmHandle _root; + int? _id; + + bool get shouldRoot => _root.isUnowned; + + RootedHandleBase(this._root, Pointer pointer, int size) : super(pointer, size) { + if (shouldRoot) { + _id = _root.addChild(this); + } + } + + @override + void releaseCore() { + if (_id != null) { + _root.removeChild(_id!); + } + } +} + +abstract class CollectionHandleBase extends RootedHandleBase { + CollectionHandleBase(super.root, super.pointer, super.size); +} diff --git a/packages/realm_dart/lib/src/native/subscription_handle.dart b/packages/realm_dart/lib/src/native/subscription_handle.dart index 3b1fad6f4..9ee90a23c 100644 --- a/packages/realm_dart/lib/src/native/subscription_handle.dart +++ b/packages/realm_dart/lib/src/native/subscription_handle.dart @@ -6,17 +6,17 @@ part of 'realm_core.dart'; class SubscriptionHandle extends HandleBase { SubscriptionHandle._(Pointer pointer) : super(pointer, 184); - ObjectId get id => _realmLib.realm_sync_subscription_id(_pointer).toDart(); + ObjectId get id => realmLib.realm_sync_subscription_id(pointer).toDart(); - String? get name => _realmLib.realm_sync_subscription_name(_pointer).toDart(); + String? get name => realmLib.realm_sync_subscription_name(pointer).toDart(); - String get objectClassName => _realmLib.realm_sync_subscription_object_class_name(_pointer).toDart()!; + String get objectClassName => realmLib.realm_sync_subscription_object_class_name(pointer).toDart()!; - String get queryString => _realmLib.realm_sync_subscription_query_string(_pointer).toDart()!; + String get queryString => realmLib.realm_sync_subscription_query_string(pointer).toDart()!; - DateTime get createdAt => _realmLib.realm_sync_subscription_created_at(_pointer).toDart(); + DateTime get createdAt => realmLib.realm_sync_subscription_created_at(pointer).toDart(); - DateTime get updatedAt => _realmLib.realm_sync_subscription_updated_at(_pointer).toDart(); + DateTime get updatedAt => realmLib.realm_sync_subscription_updated_at(pointer).toDart(); - bool equalTo(SubscriptionHandle other) => _realmLib.realm_equals(_pointer.cast(), other._pointer.cast()); + bool equalTo(SubscriptionHandle other) => realmLib.realm_equals(pointer.cast(), other.pointer.cast()); } diff --git a/packages/realm_dart/lib/src/native/subscription_set_handle.dart b/packages/realm_dart/lib/src/native/subscription_set_handle.dart index 017eae39c..42d49978f 100644 --- a/packages/realm_dart/lib/src/native/subscription_set_handle.dart +++ b/packages/realm_dart/lib/src/native/subscription_set_handle.dart @@ -9,22 +9,22 @@ class SubscriptionSetHandle extends RootedHandleBase pointer, RealmHandle root) : super(root, pointer, 128); - void refresh() => invokeGetBool(() => _realmLib.realm_sync_subscription_set_refresh(_pointer)); + void refresh() => invokeGetBool(() => realmLib.realm_sync_subscription_set_refresh(pointer)); - int get size => _realmLib.realm_sync_subscription_set_size(_pointer); + int get size => realmLib.realm_sync_subscription_set_size(pointer); Exception? get error { - final error = _realmLib.realm_sync_subscription_set_error_str(_pointer); + final error = realmLib.realm_sync_subscription_set_error_str(pointer); final message = error.cast().toRealmDartString(treatEmptyAsNull: true); return message == null ? null : RealmException(message); } - SubscriptionHandle operator [](int index) => SubscriptionHandle._(invokeGetPointer(() => _realmLib.realm_sync_subscription_at(_pointer, index))); + SubscriptionHandle operator [](int index) => SubscriptionHandle._(invokeGetPointer(() => realmLib.realm_sync_subscription_at(pointer, index))); SubscriptionHandle? findByName(String name) { return using((arena) { - final result = _realmLib.realm_sync_find_subscription_by_name( - _pointer, + final result = realmLib.realm_sync_find_subscription_by_name( + pointer, name.toCharPtr(arena), ); return result == nullptr ? null : SubscriptionHandle._(result); @@ -32,19 +32,19 @@ class SubscriptionSetHandle extends RootedHandleBase _realmLib.realm_sync_subscription_set_version(_pointer); + int get version => realmLib.realm_sync_subscription_set_version(pointer); - SubscriptionSetState get state => SubscriptionSetState.values[_realmLib.realm_sync_subscription_set_state(_pointer)]; + SubscriptionSetState get state => SubscriptionSetState.values[realmLib.realm_sync_subscription_set_state(pointer)]; MutableSubscriptionSetHandle toMutable() => - MutableSubscriptionSetHandle._(invokeGetPointer(() => _realmLib.realm_sync_make_subscription_set_mutable(_pointer)), _root); + MutableSubscriptionSetHandle._(invokeGetPointer(() => realmLib.realm_sync_make_subscription_set_mutable(pointer)), _root); static void _stateChangeCallback(Object userdata, int state) { final completer = userdata as CancellableCompleter; @@ -57,9 +57,9 @@ class SubscriptionSetHandle extends RootedHandleBase(cancellationToken); if (!completer.isCancelled) { final callback = Pointer.fromFunction(_stateChangeCallback); - final userdata = _realmLib.realm_dart_userdata_async_new(completer, callback.cast(), scheduler.handle._pointer); - _realmLib.realm_sync_on_subscription_set_state_change_async(_pointer, notifyWhen.index, - _realmLib.addresses.realm_dart_sync_on_subscription_state_changed_callback, userdata.cast(), _realmLib.addresses.realm_dart_userdata_async_free); + final userdata = realmLib.realm_dart_userdata_async_new(completer, callback.cast(), scheduler.handle.pointer); + realmLib.realm_sync_on_subscription_set_state_change_async(pointer, notifyWhen.index, + realmLib.addresses.realm_dart_sync_on_subscription_state_changed_callback, userdata.cast(), realmLib.addresses.realm_dart_userdata_async_free); } return completer.future; } diff --git a/packages/realm_dart/lib/src/realm_class.dart b/packages/realm_dart/lib/src/realm_class.dart index 12e53b51d..356a7ca3f 100644 --- a/packages/realm_dart/lib/src/realm_class.dart +++ b/packages/realm_dart/lib/src/realm_class.dart @@ -11,8 +11,7 @@ import 'package:realm_common/realm_common.dart'; import 'configuration.dart'; import 'list.dart'; -import 'logging.dart'; -import 'map.dart'; +import 'native/handle_base.dart'; import 'native/realm_core.dart'; import 'realm_object.dart'; import 'results.dart'; diff --git a/packages/realm_dart/lib/src/realm_object.dart b/packages/realm_dart/lib/src/realm_object.dart index b65dd715a..8218f9850 100644 --- a/packages/realm_dart/lib/src/realm_object.dart +++ b/packages/realm_dart/lib/src/realm_object.dart @@ -9,7 +9,9 @@ import 'package:realm_common/realm_common.dart'; import 'configuration.dart'; import 'list.dart'; +import 'native/handle_base.dart'; import 'native/realm_core.dart'; +import 'native/realm_library.dart'; import 'realm_class.dart'; import 'results.dart'; import 'map.dart'; diff --git a/packages/realm_dart/lib/src/results.dart b/packages/realm_dart/lib/src/results.dart index df92d8ef9..a3f816161 100644 --- a/packages/realm_dart/lib/src/results.dart +++ b/packages/realm_dart/lib/src/results.dart @@ -7,6 +7,7 @@ import 'dart:ffi'; import 'package:cancellation_token/cancellation_token.dart'; import 'collections.dart'; +import 'native/handle_base.dart'; import 'native/realm_core.dart'; import 'realm_class.dart'; import 'realm_object.dart'; diff --git a/packages/realm_dart/lib/src/set.dart b/packages/realm_dart/lib/src/set.dart index bcfe9d3f3..ce79e1f7e 100644 --- a/packages/realm_dart/lib/src/set.dart +++ b/packages/realm_dart/lib/src/set.dart @@ -8,6 +8,7 @@ import 'dart:ffi'; import 'package:collection/collection.dart' as collection; +import 'native/handle_base.dart'; import 'native/realm_core.dart'; import 'realm_class.dart'; import 'realm_object.dart'; diff --git a/packages/realm_dart/lib/src/subscription.dart b/packages/realm_dart/lib/src/subscription.dart index 5932c3b06..b0592ef35 100644 --- a/packages/realm_dart/lib/src/subscription.dart +++ b/packages/realm_dart/lib/src/subscription.dart @@ -112,7 +112,7 @@ enum SubscriptionSetState { /// Realm is an expensive operation server-side, even if there's very little data that needs /// downloading. /// {@category Sync} -sealed class SubscriptionSet with IterableMixin implements Finalizable { +sealed class SubscriptionSet with Iterable implements Finalizable { final Realm _realm; SubscriptionSetHandle _handle; @@ -244,7 +244,7 @@ final class MutableSubscriptionSet extends SubscriptionSet { Subscription._(_handle.insertOrAssignSubscription(query, name, update)); /// Removes the [subscription] from the set, if it exists. - bool remove(Subscription subscription) => _handle.erase(subscription); + bool remove(Subscription subscription) => _handle.erase(subscription._handle); /// Removes the [query] from the set, if it exists. bool removeByQuery(RealmResults query) => _handle.eraseByResults(query); From 1db591842d97289695c61476a344601d46bb7838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Tue, 12 Mar 2024 11:10:23 +0100 Subject: [PATCH 03/68] Fix regression: Check if close on handle deref --- packages/realm_dart/lib/src/subscription.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/realm_dart/lib/src/subscription.dart b/packages/realm_dart/lib/src/subscription.dart index b0592ef35..9d2d8b546 100644 --- a/packages/realm_dart/lib/src/subscription.dart +++ b/packages/realm_dart/lib/src/subscription.dart @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 import 'dart:core'; -import 'dart:collection'; import 'dart:ffi'; import 'native/realm_core.dart'; @@ -114,9 +113,10 @@ enum SubscriptionSetState { /// {@category Sync} sealed class SubscriptionSet with Iterable implements Finalizable { final Realm _realm; - SubscriptionSetHandle _handle; + SubscriptionSetHandle __handle; + SubscriptionSetHandle get _handle => !__handle.released ? __handle : throw RealmClosedError('Cannot access a SubscriptionSet that belongs to a closed Realm'); - SubscriptionSet._(this._realm, this._handle); + SubscriptionSet._(this._realm, this.__handle); /// Finds an existing [Subscription] in this set by its query /// From 8eeb897c2e708e9877afb1a9145147e600d76c61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Tue, 12 Mar 2024 11:11:57 +0100 Subject: [PATCH 04/68] TMP: Skip some tests (something broke with RootedHandle) --- packages/realm_dart/test/configuration_test.dart | 2 +- packages/realm_dart/test/migration_test.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/realm_dart/test/configuration_test.dart b/packages/realm_dart/test/configuration_test.dart index aa512c948..5bcfb0ceb 100644 --- a/packages/realm_dart/test/configuration_test.dart +++ b/packages/realm_dart/test/configuration_test.dart @@ -367,7 +367,7 @@ void main() { final peopleAgain = realm.all(); expect(peopleAgain.length, 1); - }); + }, skip: 'TMP: Broken after handle refactoring'); test('Configuration.shouldCompact can return false', () { var invoked = false; diff --git a/packages/realm_dart/test/migration_test.dart b/packages/realm_dart/test/migration_test.dart index 72179465c..7900e74ab 100644 --- a/packages/realm_dart/test/migration_test.dart +++ b/packages/realm_dart/test/migration_test.dart @@ -172,7 +172,7 @@ void main() { expect(students[2].name, 'Peter'); expect(students[2].number, 2); - }); + }, skip: 'TMP: Broken after handle refactoring'); test('Migration can find old object in new realm', () { final v1Config = Configuration.local([StudentV1.schema], schemaVersion: 1); @@ -436,7 +436,7 @@ void main() { expect(() => oldPlayers.handle.released, throws()); expect(() => newPlayers.handle.released, throws()); - }); + }, skip: 'TMP: Broken after handle refactoring'); test('LocalConfiguration.shouldDeleteIfMigrationNeeded deletes Realm', () { final config = Configuration.local([PersonIntName.schema]); From 8d8b6e55760eeb4eeed060d63cf0443c6a27fdaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Tue, 12 Mar 2024 14:35:00 +0100 Subject: [PATCH 05/68] Ups! --- packages/realm_dart/lib/src/subscription.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/realm_dart/lib/src/subscription.dart b/packages/realm_dart/lib/src/subscription.dart index 9d2d8b546..b418310b5 100644 --- a/packages/realm_dart/lib/src/subscription.dart +++ b/packages/realm_dart/lib/src/subscription.dart @@ -196,6 +196,8 @@ extension SubscriptionSetInternal on SubscriptionSet { _handle.keepAlive(); } + SubscriptionSetHandle get handle => _handle; + static SubscriptionSet create(Realm realm, SubscriptionSetHandle handle) => ImmutableSubscriptionSet._(realm, handle); } From 47f98af5da540aedc9ac16f956852c187379d569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Tue, 12 Mar 2024 22:21:15 +0100 Subject: [PATCH 06/68] Wip --- packages/realm_dart/lib/src/subscription.dart | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/realm_dart/lib/src/subscription.dart b/packages/realm_dart/lib/src/subscription.dart index b418310b5..880b75208 100644 --- a/packages/realm_dart/lib/src/subscription.dart +++ b/packages/realm_dart/lib/src/subscription.dart @@ -114,7 +114,8 @@ enum SubscriptionSetState { sealed class SubscriptionSet with Iterable implements Finalizable { final Realm _realm; SubscriptionSetHandle __handle; - SubscriptionSetHandle get _handle => !__handle.released ? __handle : throw RealmClosedError('Cannot access a SubscriptionSet that belongs to a closed Realm'); + SubscriptionSetHandle get _handle => __handle.nullPtrAsNull ?? (throw RealmClosedError('Cannot access a SubscriptionSet that belongs to a closed Realm')); + set _handle(SubscriptionSetHandle value) => __handle = value; SubscriptionSet._(this._realm, this.__handle); @@ -206,15 +207,15 @@ final class ImmutableSubscriptionSet extends SubscriptionSet { @override void update(void Function(MutableSubscriptionSet mutableSubscriptions) action) { - final mutableSubscriptions = MutableSubscriptionSet._(_realm, _handle.toMutable()); - final oldHandle = _handle; + final old = _handle; + final mutable = _handle.toMutable(); try { - action(mutableSubscriptions); - __handle = mutableSubscriptions._handle.commit(); + action(MutableSubscriptionSet._(_realm, mutable)); + _handle = mutable.commit(); } finally { // Release as early as possible, as we cannot start new update, until this is released! - mutableSubscriptions._handle.release(); - oldHandle.release(); + mutable.release(); + old.release(); } } } From 4f0e48c3c83a002b107c302f6dc238a03d82549a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Wed, 20 Mar 2024 14:15:08 +0100 Subject: [PATCH 07/68] After rebase --- .../realm_dart/lib/src/native/realm_core.dart | 67 ++++++++----------- packages/realm_dart/lib/src/realm_class.dart | 2 + 2 files changed, 29 insertions(+), 40 deletions(-) diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 0589b04fd..2b72335d6 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -14,7 +14,6 @@ import 'package:cancellation_token/cancellation_token.dart'; import 'package:crypto/crypto.dart'; // Hide StringUtf8Pointer.toNativeUtf8 and StringUtf16Pointer since these allows silently allocating memory. Use toUtf8Ptr instead import 'package:ffi/ffi.dart' hide StringUtf8Pointer, StringUtf16Pointer; -import 'package:logging/logging.dart'; import 'package:path/path.dart' as path; import 'package:pubspec_parse/pubspec_parse.dart'; import 'package:realm_common/realm_common.dart' as common show Decimal128; @@ -26,6 +25,7 @@ import '../configuration.dart'; import '../credentials.dart'; import '../init.dart'; import '../list.dart'; +import '../logging.dart'; import '../map.dart'; import '../migration.dart'; import '../realm_class.dart'; @@ -36,18 +36,18 @@ import '../session.dart'; import '../set.dart'; //import '../subscription.dart'; import '../user.dart'; +import 'handle_base.dart'; import 'realm_bindings.dart'; import 'realm_library.dart'; -import 'handle_base.dart'; // TODO: Use regular part 'convert.dart'; part 'decimal128.dart'; part 'error_handling.dart'; part 'mutable_subscription_set_handle.dart'; +part 'rooted_handle.dart'; part 'subscription_handle.dart'; part 'subscription_set_handle.dart'; -part 'rooted_handle.dart'; final _pluginLib = () { if (!isFlutterPlatform) { @@ -93,20 +93,20 @@ class _RealmCore { // This prevents reentrance if `realmCore` global variable is accessed during _RealmCore construction realmCore = this; - _realmLib.realm_dart_init_debug_logger(); + realmLib.realm_dart_init_debug_logger(); } void loggerAttach() { - _realmLib.realm_dart_attach_logger(scheduler.nativePort); + realmLib.realm_dart_attach_logger(scheduler.nativePort); } void loggerDetach() { - _realmLib.realm_dart_detach_logger(scheduler.nativePort); + realmLib.realm_dart_detach_logger(scheduler.nativePort); } // for debugging only. Enable in realm_dart.cpp // void invokeGC() { - // _realmLib.realm_dart_gc(); + // realmLib.realm_dart_gc(); // } SchemaHandle _createSchema(Iterable schema) { @@ -203,7 +203,7 @@ class _RealmCore { realmLib.realm_config_set_max_number_of_active_versions(configHandle.pointer, config.maxNumberOfActiveVersions!); } if (config is LocalConfiguration) { - //_realmLib.realm_config_set_schema_mode(configHandle._pointer, realm_schema_mode.RLM_SCHEMA_MODE_ADDITIVE_DISCOVERED); + //realmLib.realm_config_set_schema_mode(configHandle.pointer, realm_schema_mode.RLM_SCHEMA_MODE_ADDITIVE_DISCOVERED); if (config.initialDataCallback != null) { realmLib.realm_config_set_data_initialization_function( configHandle.pointer, @@ -292,7 +292,7 @@ class _RealmCore { // For sync and for dynamic Realms, we need to have a complete view of the schema in Core. if (config.schemaObjects.isEmpty || config is FlexibleSyncConfiguration) { - _realmLib.realm_config_set_schema_subset_mode(configHandle._pointer, realm_schema_subset_mode.RLM_SCHEMA_SUBSET_MODE_COMPLETE); + realmLib.realm_config_set_schema_subset_mode(configHandle.pointer, realm_schema_subset_mode.RLM_SCHEMA_SUBSET_MODE_COMPLETE); } return configHandle; @@ -759,12 +759,11 @@ class _RealmCore { Map _getPropertiesMetadata(Realm realm, int classKey, String? primaryKeyName, Arena arena) { final propertyCountPtr = arena(); - _realmLib.invokeGetBool( - () => _realmLib.realm_get_property_keys(realm.handle._pointer, classKey, nullptr, 0, propertyCountPtr), "Error getting property count"); + invokeGetBool(() => realmLib.realm_get_property_keys(realm.handle.pointer, classKey, nullptr, 0, propertyCountPtr), "Error getting property count"); var propertyCount = propertyCountPtr.value; final propertiesPtr = arena(propertyCount); - _realmLib.invokeGetBool(() => _realmLib.realm_get_class_properties(realm.handle._pointer, classKey, propertiesPtr, propertyCount, propertyCountPtr), + invokeGetBool(() => realmLib.realm_get_class_properties(realm.handle.pointer, classKey, propertiesPtr, propertyCount, propertyCountPtr), "Error getting class properties."); propertyCount = propertyCountPtr.value; @@ -783,16 +782,6 @@ class _RealmCore { return result; } - RealmObjectHandle createRealmObject(Realm realm, int classKey) { - final realmPtr = _realmLib.invokeGetPointer(() => _realmLib.realm_object_create(realm.handle._pointer, classKey)); - return RealmObjectHandle._(realmPtr, realm.handle); - } - - RealmObjectHandle createEmbeddedObject(RealmObjectBase obj, int propertyKey) { - final objectPtr = _realmLib.invokeGetPointer(() => _realmLib.realm_set_embedded(obj.handle._pointer, propertyKey)); - return RealmObjectHandle._(objectPtr, obj.realm.handle); - } - RealmObjectHandle createRealmObject(Realm realm, int classKey) => RealmObjectHandle.create(realm.handle, classKey); RealmObjectHandle createEmbeddedObject(RealmObjectBase obj, int propertyKey) => RealmObjectHandle.createEmbedded(obj.handle, propertyKey); @@ -1638,8 +1627,8 @@ class _RealmCore { } RealmCallbackTokenHandle subscribeForSchemaNotifications(Realm realm) { - final pointer = _realmLib.invokeGetPointer(() => _realmLib.realm_add_schema_changed_callback(realm.handle._pointer, - Pointer.fromFunction(schema_change_callback), realm.toPersistentHandle(), _realmLib.addresses.realm_dart_delete_persistent_handle)); + final pointer = invokeGetPointer(() => realmLib.realm_add_schema_changed_callback(realm.handle.pointer, Pointer.fromFunction(schema_change_callback), + realm.toPersistentHandle(), realmLib.addresses.realm_dart_delete_persistent_handle)); return RealmCallbackTokenHandle._(pointer, realm.handle); } @@ -1893,7 +1882,7 @@ class _RealmCore { void logMessage(LogCategory category, LogLevel logLevel, String message) { return using((arena) { - _realmLib.realm_dart_log(logLevel.index, category.toString().toCharPtr(arena), message.toCharPtr(arena)); + realmLib.realm_dart_log(logLevel.index, category.toString().toCharPtr(arena), message.toCharPtr(arena)); }); } @@ -2862,22 +2851,20 @@ class _RealmCore { } } -void setLogLevel(LogLevel level, {required LogCategory category}) { -using((arena) { -_realmLib.realm_set_log_level_category(category.toString().toCharPtr(arena), level.index); -}); -} - -List getAllCategoryNames() { -return using((arena) { -final count = _realmLib.realm_get_category_names(0, nullptr); -final out_values = arena>(count); -_realmLib.realm_get_category_names(count, out_values); -return [for (int i = 0; i < count; i++) out_values[i].cast().toDartString()]; -}); -} -} + void setLogLevel(LogLevel level, {required LogCategory category}) { + using((arena) { + realmLib.realm_set_log_level_category(category.toString().toCharPtr(arena), level.index); + }); + } + List getAllCategoryNames() { + return using((arena) { + final count = realmLib.realm_get_category_names(0, nullptr); + final out_values = arena>(count); + realmLib.realm_get_category_names(count, out_values); + return [for (int i = 0; i < count; i++) out_values[i].cast().toDartString()]; + }); + } } class SchemaHandle extends HandleBase { diff --git a/packages/realm_dart/lib/src/realm_class.dart b/packages/realm_dart/lib/src/realm_class.dart index 356a7ca3f..5f30f8dea 100644 --- a/packages/realm_dart/lib/src/realm_class.dart +++ b/packages/realm_dart/lib/src/realm_class.dart @@ -11,6 +11,8 @@ import 'package:realm_common/realm_common.dart'; import 'configuration.dart'; import 'list.dart'; +import 'logging.dart'; +import 'map.dart'; import 'native/handle_base.dart'; import 'native/realm_core.dart'; import 'realm_object.dart'; From b626fab0a01dd9f55d758dc22d8011b04c39179e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Wed, 27 Mar 2024 08:30:30 +0100 Subject: [PATCH 08/68] wip --- .../realm_dart/lib/src/native/subscription_set_handle.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/realm_dart/lib/src/native/subscription_set_handle.dart b/packages/realm_dart/lib/src/native/subscription_set_handle.dart index 42d49978f..d330b6248 100644 --- a/packages/realm_dart/lib/src/native/subscription_set_handle.dart +++ b/packages/realm_dart/lib/src/native/subscription_set_handle.dart @@ -16,7 +16,7 @@ class SubscriptionSetHandle extends RootedHandleBase().toRealmDartString(treatEmptyAsNull: true); - return message == null ? null : RealmException(message); + return message.convert(RealmException.new); } SubscriptionHandle operator [](int index) => SubscriptionHandle._(invokeGetPointer(() => realmLib.realm_sync_subscription_at(pointer, index))); @@ -27,7 +27,7 @@ class SubscriptionSetHandle extends RootedHandleBase realmLib.realm_sync_subscription_set_version(pointer); From 4d7d9797bf265444b5ffc06aff9770f821130bdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Fri, 12 Apr 2024 11:57:34 +0200 Subject: [PATCH 09/68] Fix after rebase --- packages/realm_dart/lib/src/native/realm_core.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 2b72335d6..13837a516 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -198,7 +198,7 @@ class _RealmCore { (FlexibleSyncConfiguration fsc) => fsc.schemaVersion, _ => 0, }; - _realmLib.realm_config_set_schema_version(configHandle._pointer, schemaVersion); + realmLib.realm_config_set_schema_version(configHandle.pointer, schemaVersion); if (config.maxNumberOfActiveVersions != null) { realmLib.realm_config_set_max_number_of_active_versions(configHandle.pointer, config.maxNumberOfActiveVersions!); } @@ -1908,7 +1908,7 @@ class _RealmCore { } String getDefaultBaseUrl() { - return _realmLib.realm_app_get_default_base_url().cast().toRealmDartString()!; + return realmLib.realm_app_get_default_base_url().cast().toRealmDartString()!; } AppHandle? getApp(String id, String? baseUrl) { From 1664e9aa7baecf2838aa804db2a1c5fb8fd5dcac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Fri, 12 Apr 2024 12:37:26 +0200 Subject: [PATCH 10/68] Revert "TMP: Skip some tests (something broke with RootedHandle)" This reverts commit 50812177a35ba3aff64860af791f6fab9e7b897d. --- packages/realm_dart/test/configuration_test.dart | 2 +- packages/realm_dart/test/migration_test.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/realm_dart/test/configuration_test.dart b/packages/realm_dart/test/configuration_test.dart index 5bcfb0ceb..aa512c948 100644 --- a/packages/realm_dart/test/configuration_test.dart +++ b/packages/realm_dart/test/configuration_test.dart @@ -367,7 +367,7 @@ void main() { final peopleAgain = realm.all(); expect(peopleAgain.length, 1); - }, skip: 'TMP: Broken after handle refactoring'); + }); test('Configuration.shouldCompact can return false', () { var invoked = false; diff --git a/packages/realm_dart/test/migration_test.dart b/packages/realm_dart/test/migration_test.dart index 7900e74ab..72179465c 100644 --- a/packages/realm_dart/test/migration_test.dart +++ b/packages/realm_dart/test/migration_test.dart @@ -172,7 +172,7 @@ void main() { expect(students[2].name, 'Peter'); expect(students[2].number, 2); - }, skip: 'TMP: Broken after handle refactoring'); + }); test('Migration can find old object in new realm', () { final v1Config = Configuration.local([StudentV1.schema], schemaVersion: 1); @@ -436,7 +436,7 @@ void main() { expect(() => oldPlayers.handle.released, throws()); expect(() => newPlayers.handle.released, throws()); - }, skip: 'TMP: Broken after handle refactoring'); + }); test('LocalConfiguration.shouldDeleteIfMigrationNeeded deletes Realm', () { final config = Configuration.local([PersonIntName.schema]); From 26db1ad50ce7a896c529b60255c8b61612e6406d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Fri, 12 Apr 2024 14:17:07 +0200 Subject: [PATCH 11/68] Use dart_test.yaml to configure tags. Make baas a tag instead of a prefix. Simplify --- packages/realm_dart/dart_test.yaml | 2 ++ packages/realm_dart/test/test.dart | 28 +++++----------------------- 2 files changed, 7 insertions(+), 23 deletions(-) create mode 100644 packages/realm_dart/dart_test.yaml diff --git a/packages/realm_dart/dart_test.yaml b/packages/realm_dart/dart_test.yaml new file mode 100644 index 000000000..8e7275b44 --- /dev/null +++ b/packages/realm_dart/dart_test.yaml @@ -0,0 +1,2 @@ +tags: + baas: { timeout: 2x } \ No newline at end of file diff --git a/packages/realm_dart/test/test.dart b/packages/realm_dart/test/test.dart index b7682133e..4824679aa 100644 --- a/packages/realm_dart/test/test.dart +++ b/packages/realm_dart/test/test.dart @@ -7,15 +7,14 @@ import 'dart:ffi'; import 'dart:io'; import 'dart:math'; import 'dart:typed_data'; -import 'package:logging/logging.dart'; import 'package:meta/meta.dart'; import 'package:path/path.dart' as _path; import 'package:realm_dart/src/logging.dart'; -import 'package:test/test.dart' hide test; -import 'package:test/test.dart' as testing; +export 'package:test/test.dart'; import 'package:realm_dart/realm.dart'; import 'package:realm_dart/src/native/realm_core.dart'; import 'package:realm_dart/src/configuration.dart'; +import 'package:test/test.dart'; import 'baas_helper.dart'; @@ -414,26 +413,9 @@ const int minInt = -9223372036854775808; const int jsMaxInt = 9007199254740991; const int jsMinInt = -9007199254740991; -//Overrides test method so we can filter tests -void test(String name, dynamic Function() testFunction, {dynamic skip, Map? onPlatform}) { - if (testName != null && !name.contains(testName!)) { - return; - } - - var timeout = 60; - assert(() { - if (Platform.environment['CI'] == null) { - timeout = Duration(minutes: 5).inSeconds; - } - - return true; - }()); - - testing.test(name, testFunction, skip: skip, onPlatform: onPlatform, timeout: Timeout(Duration(seconds: timeout))); -} void xtest(String? name, dynamic Function() testFunction, {dynamic skip, Map? onPlatform}) { - testing.test(name, testFunction, skip: "Test is disabled"); + test(name, testFunction, skip: "Test is disabled"); } BaasHelper? baasHelper; @@ -444,7 +426,7 @@ void setupTests() { Realm.logger.setLogLevel(LogLevel.detail); Realm.logger.onRecord.listen((record) { - testing.printOnFailure('${record.category} ${record.level.name}: ${record.message}'); + printOnFailure('${record.category} ${record.level.name}: ${record.message}'); }); // Enable this to print platform info, including current PID @@ -603,7 +585,7 @@ Future baasTest( baasHelper!.printSplunkLogLink(appName, baasHelper?.baseUrl); final config = await baasHelper!.getAppConfig(appName: appName); await testFunction(config); - }, skip: skip); + }, skip: skip, tags: 'baas'); } dynamic shouldSkip(dynamic skip) { From f16caef80fd897b8d8f36d4a6acdb7736f6670de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Fri, 12 Apr 2024 14:17:40 +0200 Subject: [PATCH 12/68] Fix nullPtr related bug --- packages/realm_dart/lib/src/native/convert.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/realm_dart/lib/src/native/convert.dart b/packages/realm_dart/lib/src/native/convert.dart index bdc39c290..d619c4f9c 100644 --- a/packages/realm_dart/lib/src/native/convert.dart +++ b/packages/realm_dart/lib/src/native/convert.dart @@ -3,6 +3,11 @@ part of 'realm_core.dart'; +extension PointerEx on Pointer { + Pointer? get nullPtrAsNull => this == nullptr ? null : this; + U? convert(U Function(Pointer) convertor) => nullPtrAsNull.convert(convertor); +} + extension HandleBaseEx on T { T? get nullPtrAsNull => pointer == nullptr ? null : this; U? convert(U Function(T) convertor) => nullPtrAsNull.convert(convertor); From a33bd254d205977ceac65269c9e0723b8e7c0f45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Fri, 12 Apr 2024 16:54:06 +0200 Subject: [PATCH 13/68] Doh! I'll go die in shame!! --- packages/realm_dart/lib/src/native/realm_core.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 13837a516..a041f7109 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -2904,7 +2904,7 @@ class RealmHandle extends HandleBase { } @override - void _releaseCore() { + void releaseCore() { final keys = _children.keys.toList(); for (final key in keys) { From fe80da43baa92428f337ee5a62f6d17a57614a8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Fri, 12 Apr 2024 17:54:02 +0200 Subject: [PATCH 14/68] Refactor RealmHandle --- .../realm_dart/lib/src/configuration.dart | 4 +- .../realm_dart/lib/src/native/realm_core.dart | 88 ++++--------------- .../lib/src/native/realm_handle.dart | 78 ++++++++++++++++ .../lib/src/native/rooted_handle.dart | 4 + 4 files changed, 99 insertions(+), 75 deletions(-) create mode 100644 packages/realm_dart/lib/src/native/realm_handle.dart diff --git a/packages/realm_dart/lib/src/configuration.dart b/packages/realm_dart/lib/src/configuration.dart index 45998fcfe..f9a5e713a 100644 --- a/packages/realm_dart/lib/src/configuration.dart +++ b/packages/realm_dart/lib/src/configuration.dart @@ -225,8 +225,8 @@ abstract class Configuration implements Finalizable { return; } - if (key.length != realmCore.encryptionKeySize) { - throw RealmException("Wrong encryption key size (must be ${realmCore.encryptionKeySize}, but was ${key.length})"); + if (key.length != encryptionKeySize) { + throw RealmException("Wrong encryption key size (must be $encryptionKeySize, but was ${key.length})"); } int notAByteElement = key.firstWhere((e) => e > 255, orElse: () => -1); diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index a041f7109..bbc2830b3 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -45,6 +45,7 @@ part 'convert.dart'; part 'decimal128.dart'; part 'error_handling.dart'; part 'mutable_subscription_set_handle.dart'; +part 'realm_handle.dart'; part 'rooted_handle.dart'; part 'subscription_handle.dart'; part 'subscription_set_handle.dart'; @@ -72,6 +73,8 @@ final _pluginLib = () { _RealmCore realmCore = _RealmCore(); +const encryptionKeySize = 64; + // All access to Realm Core functionality goes through this class class _RealmCore { // From realm.h. Currently not exported from the shared library @@ -82,7 +85,6 @@ class _RealmCore { // ignore: unused_field, constant_identifier_names static const int RLM_INVALID_OBJECT_KEY = -1; - final encryptionKeySize = 64; // ignore: unused_field static late final _RealmCore _instance; @@ -109,7 +111,7 @@ class _RealmCore { // realmLib.realm_dart_gc(); // } - SchemaHandle _createSchema(Iterable schema) { + static SchemaHandle _createSchema(Iterable schema) { return using((Arena arena) { final classCount = schema.length; @@ -173,7 +175,7 @@ class _RealmCore { }); } - ConfigHandle _createConfig(Configuration config) { + static ConfigHandle _createConfig(Configuration config) { return using((Arena arena) { final configPtr = realmLib.realm_config_new(); final configHandle = ConfigHandle._(configPtr); @@ -2791,13 +2793,7 @@ class _RealmCore { }); } - bool compact(Realm realm) { - return using((arena) { - final out_did_compact = arena(); - invokeGetBool(() => realmLib.realm_compact(realm.handle.pointer, out_did_compact)); - return out_did_compact.value; - }); - } + bool compact(Realm realm) => realm.handle.compact(); bool immediatelyRunFileActions(App app, String realmPath) { return using((arena) { @@ -2877,42 +2873,6 @@ class ConfigHandle extends HandleBase { ConfigHandle._(Pointer pointer) : super(pointer, 512); } -class RealmHandle extends HandleBase { - int _counter = 0; - - final Map> _children = {}; - - RealmHandle._(Pointer pointer) : super(pointer, 24); - - RealmHandle._unowned(super.pointer) : super.unowned(); - - int addChild(RootedHandleBase child) { - final id = _counter++; - _children[id] = WeakReference(child); - rootedHandleFinalizer.attach(this, FinalizationToken(this, id), detach: this); - return id; - } - - void removeChild(int id) { - final child = _children.remove(id); - if (child != null) { - final target = child.target; - if (target != null) { - rootedHandleFinalizer.detach(target); - } - } - } - - @override - void releaseCore() { - final keys = _children.keys.toList(); - - for (final key in keys) { - _children[key]?.target?.release(); - } - } -} - class SchedulerHandle extends HandleBase { SchedulerHandle._(Pointer pointer) : super(pointer, 24); } @@ -2920,37 +2880,19 @@ class SchedulerHandle extends HandleBase { class RealmObjectHandle extends RootedHandleBase { RealmObjectHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 112); - factory RealmObjectHandle.createWithPrimaryKey(RealmHandle realm, int classKey, Object? primaryKey) { - return using((Arena arena) { - final realm_value = _toRealmValue(primaryKey, arena); - final realmPtr = invokeGetPointer(() => realmLib.realm_object_create_with_primary_key(realm.pointer, classKey, realm_value.ref)); - return RealmObjectHandle._(realmPtr, realm); - }); - } + factory RealmObjectHandle.createWithPrimaryKey(RealmHandle realm, int classKey, Object? primaryKey) => realm.createWithPrimaryKey(classKey, primaryKey); - factory RealmObjectHandle.create(RealmHandle realm, int classKey) { - final realmPtr = invokeGetPointer(() => realmLib.realm_object_create(realm.pointer, classKey)); - return RealmObjectHandle._(realmPtr, realm); - } + factory RealmObjectHandle.create(RealmHandle realm, int classKey) => realm.create(classKey); - factory RealmObjectHandle.createEmbedded(RealmObjectHandle parent, int propertyKey) { - final objectPtr = invokeGetPointer(() => realmLib.realm_set_embedded(parent.pointer, propertyKey)); - return RealmObjectHandle._(objectPtr, parent._root); - } + factory RealmObjectHandle.createEmbedded(RealmObjectHandle parent, int propertyKey) => parent.createEmbedded(propertyKey); - factory RealmObjectHandle.getOrCreateWithPrimaryKey(RealmHandle realm, int classKey, Object? primaryKey) { - return using((Arena arena) { - final realm_value = _toRealmValue(primaryKey, arena); - final didCreate = arena(); - final realmPtr = invokeGetPointer(() => realmLib.realm_object_get_or_create_with_primary_key( - realm.pointer, - classKey, - realm_value.ref, - didCreate, - )); - return RealmObjectHandle._(realmPtr, realm); - }); + RealmObjectHandle createEmbedded(int propertyKey) { + final objectPtr = invokeGetPointer(() => realmLib.realm_set_embedded(pointer, propertyKey)); + return RealmObjectHandle._(objectPtr, _root); } + + factory RealmObjectHandle.getOrCreateWithPrimaryKey(RealmHandle realm, int classKey, Object? primaryKey) => + realm.getOrCreateWithPrimaryKey(classKey, primaryKey); } class _RealmLinkHandle { diff --git a/packages/realm_dart/lib/src/native/realm_handle.dart b/packages/realm_dart/lib/src/native/realm_handle.dart new file mode 100644 index 000000000..0da17ef80 --- /dev/null +++ b/packages/realm_dart/lib/src/native/realm_handle.dart @@ -0,0 +1,78 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + +part of 'realm_core.dart'; + +class RealmHandle extends HandleBase { + int _counter = 0; + + final Map> _children = {}; + + RealmHandle._(Pointer pointer) : super(pointer, 24); + + RealmHandle._unowned(super.pointer) : super.unowned(); + + int addChild(RootedHandleBase child) { + final id = _counter++; + _children[id] = WeakReference(child); + rootedHandleFinalizer.attach(this, FinalizationToken(this, id), detach: this); + return id; + } + + void removeChild(int id) { + final child = _children.remove(id); + if (child != null) { + final target = child.target; + if (target != null) { + rootedHandleFinalizer.detach(target); + } + } + } + + @override + void releaseCore() { + for (final child in _children.values.toList()) { + child.target?.release(); + } + } + + RealmObjectHandle createWithPrimaryKey(int classKey, Object? primaryKey) { + return using((Arena arena) { + final realmValue = _toRealmValue(primaryKey, arena); + final realmPtr = invokeGetPointer(() => realmLib.realm_object_create_with_primary_key(pointer, classKey, realmValue.ref)); + return RealmObjectHandle._(realmPtr, this); + }); + } + + RealmObjectHandle create(int classKey) { + final realmPtr = invokeGetPointer(() => realmLib.realm_object_create(pointer, classKey)); + return RealmObjectHandle._(realmPtr, this); + } + + RealmObjectHandle getOrCreateWithPrimaryKey(int classKey, Object? primaryKey) { + return using((Arena arena) { + final realmValue = _toRealmValue(primaryKey, arena); + final didCreate = arena(); + final realmPtr = invokeGetPointer(() => realmLib.realm_object_get_or_create_with_primary_key( + pointer, + classKey, + realmValue.ref, + didCreate, + )); + return RealmObjectHandle._(realmPtr, this); + }); + } + + bool compact() { + return using((arena) { + final outDidCompact = arena(); + invokeGetBool(() => realmLib.realm_compact(pointer, outDidCompact)); + return outDidCompact.value; + }); + } + + void writeCopy(Configuration config) { + final configHandle = _RealmCore._createConfig(config); + invokeGetBool(() => realmLib.realm_convert_with_config(pointer, configHandle.pointer, false)); + } +} diff --git a/packages/realm_dart/lib/src/native/rooted_handle.dart b/packages/realm_dart/lib/src/native/rooted_handle.dart index 1dd2e2bf5..11bb4fc7b 100644 --- a/packages/realm_dart/lib/src/native/rooted_handle.dart +++ b/packages/realm_dart/lib/src/native/rooted_handle.dart @@ -1,3 +1,6 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + part of 'realm_core.dart'; class FinalizationToken { @@ -37,3 +40,4 @@ abstract class RootedHandleBase extends HandleBase { abstract class CollectionHandleBase extends RootedHandleBase { CollectionHandleBase(super.root, super.pointer, super.size); } + From 0b6d1b60a8400b90580be6ac3f8603dab1daf281 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Sat, 13 Apr 2024 11:43:04 +0200 Subject: [PATCH 15/68] Refactor ConfigHandle --- .../lib/src/native/config_handle.dart | 157 ++++++++ .../realm_dart/lib/src/native/realm_core.dart | 346 +++++------------- .../lib/src/native/realm_handle.dart | 2 +- packages/realm_dart/lib/src/realm_class.dart | 2 +- .../realm_dart/test/configuration_test.dart | 3 +- packages/realm_dart/test/realm_test.dart | 1 - packages/realm_dart/test/test.dart | 1 - 7 files changed, 256 insertions(+), 256 deletions(-) create mode 100644 packages/realm_dart/lib/src/native/config_handle.dart diff --git a/packages/realm_dart/lib/src/native/config_handle.dart b/packages/realm_dart/lib/src/native/config_handle.dart new file mode 100644 index 000000000..85e619709 --- /dev/null +++ b/packages/realm_dart/lib/src/native/config_handle.dart @@ -0,0 +1,157 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + +part of 'realm_core.dart'; + +class ConfigHandle extends HandleBase { + ConfigHandle._(Pointer pointer) : super(pointer, 512); + + factory ConfigHandle(Configuration config) { + return using((Arena arena) { + final configPtr = realmLib.realm_config_new(); + final configHandle = ConfigHandle._(configPtr); + + if (config.schemaObjects.isNotEmpty) { + final schemaHandle = _RealmCore._createSchema(config.schemaObjects); + realmLib.realm_config_set_schema(configHandle.pointer, schemaHandle.pointer); + } + + realmLib.realm_config_set_path(configHandle.pointer, config.path.toCharPtr(arena)); + realmLib.realm_config_set_scheduler(configHandle.pointer, scheduler.handle.pointer); + + if (config.fifoFilesFallbackPath != null) { + realmLib.realm_config_set_fifo_path(configHandle.pointer, config.fifoFilesFallbackPath!.toCharPtr(arena)); + } + + // Setting schema version only makes sense for local realms, but core insists it is always set, + // hence we set it to 0 in those cases. + + final schemaVersion = switch (config) { + (LocalConfiguration lc) => lc.schemaVersion, + (FlexibleSyncConfiguration fsc) => fsc.schemaVersion, + _ => 0, + }; + realmLib.realm_config_set_schema_version(configHandle.pointer, schemaVersion); + if (config.maxNumberOfActiveVersions != null) { + realmLib.realm_config_set_max_number_of_active_versions(configHandle.pointer, config.maxNumberOfActiveVersions!); + } + if (config is LocalConfiguration) { + //realmLib.realm_config_set_schema_mode(configHandle.pointer, realm_schema_mode.RLM_SCHEMA_MODE_ADDITIVE_DISCOVERED); + if (config.initialDataCallback != null) { + realmLib.realm_config_set_data_initialization_function( + configHandle.pointer, + Pointer.fromFunction(initial_data_callback, false), + config.toPersistentHandle(), + realmLib.addresses.realm_dart_delete_persistent_handle, + ); + } + if (config.isReadOnly) { + realmLib.realm_config_set_schema_mode(configHandle.pointer, realm_schema_mode.RLM_SCHEMA_MODE_IMMUTABLE); + } else if (config.shouldDeleteIfMigrationNeeded) { + realmLib.realm_config_set_schema_mode(configHandle.pointer, realm_schema_mode.RLM_SCHEMA_MODE_SOFT_RESET_FILE); + } + if (config.disableFormatUpgrade) { + realmLib.realm_config_set_disable_format_upgrade(configHandle.pointer, config.disableFormatUpgrade); + } + if (config.shouldCompactCallback != null) { + realmLib.realm_config_set_should_compact_on_launch_function( + configHandle.pointer, + Pointer.fromFunction(should_compact_callback, false), + config.toPersistentHandle(), + realmLib.addresses.realm_dart_delete_persistent_handle, + ); + } + if (config.migrationCallback != null) { + realmLib.realm_config_set_migration_function( + configHandle.pointer, + Pointer.fromFunction(migration_callback, false), + config.toPersistentHandle(), + realmLib.addresses.realm_dart_delete_persistent_handle, + ); + } + } else if (config is InMemoryConfiguration) { + realmLib.realm_config_set_in_memory(configHandle.pointer, true); + } else if (config is FlexibleSyncConfiguration) { + realmLib.realm_config_set_schema_mode(configHandle.pointer, realm_schema_mode.RLM_SCHEMA_MODE_ADDITIVE_DISCOVERED); + final syncConfigPtr = invokeGetPointer(() => realmLib.realm_flx_sync_config_new(config.user.handle.pointer)); + try { + realmLib.realm_sync_config_set_session_stop_policy(syncConfigPtr, config.sessionStopPolicy.index); + realmLib.realm_sync_config_set_resync_mode(syncConfigPtr, config.clientResetHandler.clientResyncMode.index); + final errorHandlerCallback = + Pointer.fromFunction, realm_sync_error_t)>(_syncErrorHandlerCallback); + final errorHandlerUserdata = realmLib.realm_dart_userdata_async_new(config, errorHandlerCallback.cast(), scheduler.handle.pointer); + realmLib.realm_sync_config_set_error_handler(syncConfigPtr, realmLib.addresses.realm_dart_sync_error_handler_callback, errorHandlerUserdata.cast(), + realmLib.addresses.realm_dart_userdata_async_free); + + if (config.clientResetHandler.onBeforeReset != null) { + final syncBeforeResetCallback = Pointer.fromFunction, Pointer)>(_syncBeforeResetCallback); + final beforeResetUserdata = realmLib.realm_dart_userdata_async_new(config, syncBeforeResetCallback.cast(), scheduler.handle.pointer); + + realmLib.realm_sync_config_set_before_client_reset_handler(syncConfigPtr, realmLib.addresses.realm_dart_sync_before_reset_handler_callback, + beforeResetUserdata.cast(), realmLib.addresses.realm_dart_userdata_async_free); + } + + if (config.clientResetHandler.onAfterRecovery != null || config.clientResetHandler.onAfterDiscard != null) { + final syncAfterResetCallback = + Pointer.fromFunction, Pointer, Bool, Pointer)>( + _syncAfterResetCallback); + final afterResetUserdata = realmLib.realm_dart_userdata_async_new(config, syncAfterResetCallback.cast(), scheduler.handle.pointer); + + realmLib.realm_sync_config_set_after_client_reset_handler(syncConfigPtr, realmLib.addresses.realm_dart_sync_after_reset_handler_callback, + afterResetUserdata.cast(), realmLib.addresses.realm_dart_userdata_async_free); + } + + if (config.shouldCompactCallback != null) { + realmLib.realm_config_set_should_compact_on_launch_function( + configHandle.pointer, + Pointer.fromFunction(should_compact_callback, false), + config.toPersistentHandle(), + realmLib.addresses.realm_dart_delete_persistent_handle, + ); + } + + realmLib.realm_config_set_sync_config(configPtr, syncConfigPtr); + } finally { + realmLib.realm_release(syncConfigPtr.cast()); + } + } else if (config is DisconnectedSyncConfiguration) { + realmLib.realm_config_set_schema_mode(configHandle.pointer, realm_schema_mode.RLM_SCHEMA_MODE_ADDITIVE_EXPLICIT); + realmLib.realm_config_set_force_sync_history(configPtr, true); + } + + if (config.encryptionKey != null) { + realmLib.realm_config_set_encryption_key(configPtr, config.encryptionKey!.toUint8Ptr(arena), encryptionKeySize); + } + + // For sync and for dynamic Realms, we need to have a complete view of the schema in Core. + if (config.schemaObjects.isEmpty || config is FlexibleSyncConfiguration) { + realmLib.realm_config_set_schema_subset_mode(configHandle.pointer, realm_schema_subset_mode.RLM_SCHEMA_SUBSET_MODE_COMPLETE); + } + + return configHandle; + }); + } +} + +void _syncAfterResetCallback(Object userdata, Pointer beforeHandle, Pointer afterReference, bool didRecover, + Pointer unlockCallbackFunc) { + _guardSynchronousCallback(() async { + final syncConfig = userdata as FlexibleSyncConfiguration; + final afterResetCallback = didRecover ? syncConfig.clientResetHandler.onAfterRecovery : syncConfig.clientResetHandler.onAfterDiscard; + + if (afterResetCallback == null) { + return; + } + + final beforeRealm = RealmInternal.getUnowned(syncConfig, RealmHandle._unowned(beforeHandle)); + final realmPtr = invokeGetPointer(() => realmLib.realm_from_thread_safe_reference(afterReference, scheduler.handle.pointer)); + final afterRealm = RealmInternal.getUnowned(syncConfig, RealmHandle._unowned(realmPtr)); + + try { + return await afterResetCallback(beforeRealm, afterRealm); + } finally { + beforeRealm.handle.release(); + afterRealm.handle.release(); + } + }, unlockCallbackFunc); +} diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index bbc2830b3..f2172f2ad 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -41,6 +41,7 @@ import 'realm_bindings.dart'; import 'realm_library.dart'; // TODO: Use regular +part 'config_handle.dart'; part 'convert.dart'; part 'decimal128.dart'; part 'error_handling.dart'; @@ -75,6 +76,97 @@ _RealmCore realmCore = _RealmCore(); const encryptionKeySize = 64; +void _guardSynchronousCallback(FutureOr Function() callback, Pointer unlockCallbackFunc) async { + Pointer user_error = nullptr; + try { + await callback(); + } catch (error) { + user_error = error.toPersistentHandle(); + } finally { + realmLib.realm_dart_invoke_unlock_callback(user_error, unlockCallbackFunc); + } +} + +bool should_compact_callback(Pointer userdata, int totalSize, int usedSize) { + final config = userdata.toObject(); + + if (config is LocalConfiguration) { + return config.shouldCompactCallback!(totalSize, usedSize); + } else if (config is FlexibleSyncConfiguration) { + return config.shouldCompactCallback!(totalSize, usedSize); + } + + return false; +} + +bool migration_callback(Pointer userdata, Pointer oldRealmHandle, Pointer newRealmHandle, Pointer schema) { + final oldHandle = RealmHandle._unowned(oldRealmHandle); + final newHandle = RealmHandle._unowned(newRealmHandle); + try { + final LocalConfiguration config = userdata.toObject(); + + final oldSchemaVersion = realmLib.realm_get_schema_version(oldRealmHandle); + final oldConfig = Configuration.local([], path: config.path, isReadOnly: true, schemaVersion: oldSchemaVersion); + final oldRealm = RealmInternal.getUnowned(oldConfig, oldHandle, isInMigration: true); + + final newRealm = RealmInternal.getUnowned(config, newHandle, isInMigration: true); + + final migration = MigrationInternal.create(RealmInternal.getMigrationRealm(oldRealm), newRealm, SchemaHandle.unowned(schema)); + config.migrationCallback!(migration, oldSchemaVersion); + return true; + } catch (ex) { + realmLib.realm_register_user_code_callback_error(ex.toPersistentHandle()); + } finally { + oldHandle.release(); + newHandle.release(); + } + + return false; +} + +void _syncErrorHandlerCallback(Object userdata, Pointer session, realm_sync_error error) { + final syncConfig = userdata as FlexibleSyncConfiguration; + // TODO: Take the app from the session instead of from syncConfig after fixing issue https://github.com/realm/realm-dart/issues/633 + final syncError = SyncErrorInternal.createSyncError(error.toDart(), app: syncConfig.user.app); + + if (syncError is ClientResetError) { + syncConfig.clientResetHandler.onManualReset?.call(syncError); + return; + } + + syncConfig.syncErrorHandler(syncError); +} + +void _syncBeforeResetCallback(Object userdata, Pointer realmHandle, Pointer unlockCallbackFunc) { + _guardSynchronousCallback(() async { + final syncConfig = userdata as FlexibleSyncConfiguration; + var beforeResetCallback = syncConfig.clientResetHandler.onBeforeReset!; + + final realm = RealmInternal.getUnowned(syncConfig, RealmHandle._unowned(realmHandle)); + try { + await beforeResetCallback(realm); + } finally { + realm.handle.release(); + } + }, unlockCallbackFunc); +} + +bool initial_data_callback(Pointer userdata, Pointer realmPtr) { + final realmHandle = RealmHandle._unowned(realmPtr); + try { + final LocalConfiguration config = userdata.toObject(); + final realm = RealmInternal.getUnowned(config, realmHandle); + config.initialDataCallback!(realm); + return true; + } catch (ex) { + realmLib.realm_register_user_code_callback_error(ex.toPersistentHandle()); + } finally { + realmHandle.release(); + } + + return false; +} + // All access to Realm Core functionality goes through this class class _RealmCore { // From realm.h. Currently not exported from the shared library @@ -175,132 +267,6 @@ class _RealmCore { }); } - static ConfigHandle _createConfig(Configuration config) { - return using((Arena arena) { - final configPtr = realmLib.realm_config_new(); - final configHandle = ConfigHandle._(configPtr); - - if (config.schemaObjects.isNotEmpty) { - final schemaHandle = _createSchema(config.schemaObjects); - realmLib.realm_config_set_schema(configHandle.pointer, schemaHandle.pointer); - } - - realmLib.realm_config_set_path(configHandle.pointer, config.path.toCharPtr(arena)); - realmLib.realm_config_set_scheduler(configHandle.pointer, scheduler.handle.pointer); - - if (config.fifoFilesFallbackPath != null) { - realmLib.realm_config_set_fifo_path(configHandle.pointer, config.fifoFilesFallbackPath!.toCharPtr(arena)); - } - - // Setting schema version only makes sense for local realms, but core insists it is always set, - // hence we set it to 0 in those cases. - - final schemaVersion = switch (config) { - (LocalConfiguration lc) => lc.schemaVersion, - (FlexibleSyncConfiguration fsc) => fsc.schemaVersion, - _ => 0, - }; - realmLib.realm_config_set_schema_version(configHandle.pointer, schemaVersion); - if (config.maxNumberOfActiveVersions != null) { - realmLib.realm_config_set_max_number_of_active_versions(configHandle.pointer, config.maxNumberOfActiveVersions!); - } - if (config is LocalConfiguration) { - //realmLib.realm_config_set_schema_mode(configHandle.pointer, realm_schema_mode.RLM_SCHEMA_MODE_ADDITIVE_DISCOVERED); - if (config.initialDataCallback != null) { - realmLib.realm_config_set_data_initialization_function( - configHandle.pointer, - Pointer.fromFunction(initial_data_callback, false), - config.toPersistentHandle(), - realmLib.addresses.realm_dart_delete_persistent_handle, - ); - } - if (config.isReadOnly) { - realmLib.realm_config_set_schema_mode(configHandle.pointer, realm_schema_mode.RLM_SCHEMA_MODE_IMMUTABLE); - } else if (config.shouldDeleteIfMigrationNeeded) { - realmLib.realm_config_set_schema_mode(configHandle.pointer, realm_schema_mode.RLM_SCHEMA_MODE_SOFT_RESET_FILE); - } - if (config.disableFormatUpgrade) { - realmLib.realm_config_set_disable_format_upgrade(configHandle.pointer, config.disableFormatUpgrade); - } - if (config.shouldCompactCallback != null) { - realmLib.realm_config_set_should_compact_on_launch_function( - configHandle.pointer, - Pointer.fromFunction(should_compact_callback, false), - config.toPersistentHandle(), - realmLib.addresses.realm_dart_delete_persistent_handle, - ); - } - if (config.migrationCallback != null) { - realmLib.realm_config_set_migration_function( - configHandle.pointer, - Pointer.fromFunction(migration_callback, false), - config.toPersistentHandle(), - realmLib.addresses.realm_dart_delete_persistent_handle, - ); - } - } else if (config is InMemoryConfiguration) { - realmLib.realm_config_set_in_memory(configHandle.pointer, true); - } else if (config is FlexibleSyncConfiguration) { - realmLib.realm_config_set_schema_mode(configHandle.pointer, realm_schema_mode.RLM_SCHEMA_MODE_ADDITIVE_DISCOVERED); - final syncConfigPtr = invokeGetPointer(() => realmLib.realm_flx_sync_config_new(config.user.handle.pointer)); - try { - realmLib.realm_sync_config_set_session_stop_policy(syncConfigPtr, config.sessionStopPolicy.index); - realmLib.realm_sync_config_set_resync_mode(syncConfigPtr, config.clientResetHandler.clientResyncMode.index); - final errorHandlerCallback = - Pointer.fromFunction, realm_sync_error_t)>(_syncErrorHandlerCallback); - final errorHandlerUserdata = realmLib.realm_dart_userdata_async_new(config, errorHandlerCallback.cast(), scheduler.handle.pointer); - realmLib.realm_sync_config_set_error_handler(syncConfigPtr, realmLib.addresses.realm_dart_sync_error_handler_callback, errorHandlerUserdata.cast(), - realmLib.addresses.realm_dart_userdata_async_free); - - if (config.clientResetHandler.onBeforeReset != null) { - final syncBeforeResetCallback = Pointer.fromFunction, Pointer)>(_syncBeforeResetCallback); - final beforeResetUserdata = realmLib.realm_dart_userdata_async_new(config, syncBeforeResetCallback.cast(), scheduler.handle.pointer); - - realmLib.realm_sync_config_set_before_client_reset_handler(syncConfigPtr, realmLib.addresses.realm_dart_sync_before_reset_handler_callback, - beforeResetUserdata.cast(), realmLib.addresses.realm_dart_userdata_async_free); - } - - if (config.clientResetHandler.onAfterRecovery != null || config.clientResetHandler.onAfterDiscard != null) { - final syncAfterResetCallback = - Pointer.fromFunction, Pointer, Bool, Pointer)>( - _syncAfterResetCallback); - final afterResetUserdata = realmLib.realm_dart_userdata_async_new(config, syncAfterResetCallback.cast(), scheduler.handle.pointer); - - realmLib.realm_sync_config_set_after_client_reset_handler(syncConfigPtr, realmLib.addresses.realm_dart_sync_after_reset_handler_callback, - afterResetUserdata.cast(), realmLib.addresses.realm_dart_userdata_async_free); - } - - if (config.shouldCompactCallback != null) { - realmLib.realm_config_set_should_compact_on_launch_function( - configHandle.pointer, - Pointer.fromFunction(should_compact_callback, false), - config.toPersistentHandle(), - realmLib.addresses.realm_dart_delete_persistent_handle, - ); - } - - realmLib.realm_config_set_sync_config(configPtr, syncConfigPtr); - } finally { - realmLib.realm_release(syncConfigPtr.cast()); - } - } else if (config is DisconnectedSyncConfiguration) { - realmLib.realm_config_set_schema_mode(configHandle.pointer, realm_schema_mode.RLM_SCHEMA_MODE_ADDITIVE_EXPLICIT); - realmLib.realm_config_set_force_sync_history(configPtr, true); - } - - if (config.encryptionKey != null) { - realmLib.realm_config_set_encryption_key(configPtr, config.encryptionKey!.toUint8Ptr(arena), encryptionKeySize); - } - - // For sync and for dynamic Realms, we need to have a complete view of the schema in Core. - if (config.schemaObjects.isEmpty || config is FlexibleSyncConfiguration) { - realmLib.realm_config_set_schema_subset_mode(configHandle.pointer, realm_schema_subset_mode.RLM_SCHEMA_SUBSET_MODE_COMPLETE); - } - - return configHandle; - }); - } - String getPathForUser(User user) { final syncConfigPtr = invokeGetPointer(() => realmLib.realm_flx_sync_config_new(user.handle.pointer)); try { @@ -315,121 +281,6 @@ class _RealmCore { return SubscriptionSetHandle._(invokeGetPointer(() => realmLib.realm_sync_get_active_subscription_set(realm.handle.pointer)), realm.handle); } - static bool initial_data_callback(Pointer userdata, Pointer realmPtr) { - final realmHandle = RealmHandle._unowned(realmPtr); - try { - final LocalConfiguration config = userdata.toObject(); - final realm = RealmInternal.getUnowned(config, realmHandle); - config.initialDataCallback!(realm); - return true; - } catch (ex) { - realmLib.realm_register_user_code_callback_error(ex.toPersistentHandle()); - } finally { - realmHandle.release(); - } - - return false; - } - - static bool should_compact_callback(Pointer userdata, int totalSize, int usedSize) { - final config = userdata.toObject(); - - if (config is LocalConfiguration) { - return config.shouldCompactCallback!(totalSize, usedSize); - } else if (config is FlexibleSyncConfiguration) { - return config.shouldCompactCallback!(totalSize, usedSize); - } - - return false; - } - - static bool migration_callback( - Pointer userdata, Pointer oldRealmHandle, Pointer newRealmHandle, Pointer schema) { - final oldHandle = RealmHandle._unowned(oldRealmHandle); - final newHandle = RealmHandle._unowned(newRealmHandle); - try { - final LocalConfiguration config = userdata.toObject(); - - final oldSchemaVersion = realmLib.realm_get_schema_version(oldRealmHandle); - final oldConfig = Configuration.local([], path: config.path, isReadOnly: true, schemaVersion: oldSchemaVersion); - final oldRealm = RealmInternal.getUnowned(oldConfig, oldHandle, isInMigration: true); - - final newRealm = RealmInternal.getUnowned(config, newHandle, isInMigration: true); - - final migration = MigrationInternal.create(RealmInternal.getMigrationRealm(oldRealm), newRealm, SchemaHandle.unowned(schema)); - config.migrationCallback!(migration, oldSchemaVersion); - return true; - } catch (ex) { - realmLib.realm_register_user_code_callback_error(ex.toPersistentHandle()); - } finally { - oldHandle.release(); - newHandle.release(); - } - - return false; - } - - static void _syncErrorHandlerCallback(Object userdata, Pointer session, realm_sync_error error) { - final syncConfig = userdata as FlexibleSyncConfiguration; - // TODO: Take the app from the session instead of from syncConfig after fixing issue https://github.com/realm/realm-dart/issues/633 - final syncError = SyncErrorInternal.createSyncError(error.toDart(), app: syncConfig.user.app); - - if (syncError is ClientResetError) { - syncConfig.clientResetHandler.onManualReset?.call(syncError); - return; - } - - syncConfig.syncErrorHandler(syncError); - } - - static void _guardSynchronousCallback(FutureOr Function() callback, Pointer unlockCallbackFunc) async { - Pointer user_error = nullptr; - try { - await callback(); - } catch (error) { - user_error = error.toPersistentHandle(); - } finally { - realmLib.realm_dart_invoke_unlock_callback(user_error, unlockCallbackFunc); - } - } - - static void _syncBeforeResetCallback(Object userdata, Pointer realmHandle, Pointer unlockCallbackFunc) { - _guardSynchronousCallback(() async { - final syncConfig = userdata as FlexibleSyncConfiguration; - var beforeResetCallback = syncConfig.clientResetHandler.onBeforeReset!; - - final realm = RealmInternal.getUnowned(syncConfig, RealmHandle._unowned(realmHandle)); - try { - await beforeResetCallback(realm); - } finally { - realm.handle.release(); - } - }, unlockCallbackFunc); - } - - static void _syncAfterResetCallback(Object userdata, Pointer beforeHandle, Pointer afterReference, bool didRecover, - Pointer unlockCallbackFunc) { - _guardSynchronousCallback(() async { - final syncConfig = userdata as FlexibleSyncConfiguration; - final afterResetCallback = didRecover ? syncConfig.clientResetHandler.onAfterRecovery : syncConfig.clientResetHandler.onAfterDiscard; - - if (afterResetCallback == null) { - return; - } - - final beforeRealm = RealmInternal.getUnowned(syncConfig, RealmHandle._unowned(beforeHandle)); - final realmPtr = invokeGetPointer(() => realmLib.realm_from_thread_safe_reference(afterReference, scheduler.handle.pointer)); - final afterRealm = RealmInternal.getUnowned(syncConfig, RealmHandle._unowned(realmPtr)); - - try { - return await afterResetCallback(beforeRealm, afterRealm); - } finally { - beforeRealm.handle.release(); - afterRealm.handle.release(); - } - }, unlockCallbackFunc); - } - void raiseError(Session session, int errorCode, bool isFatal) { using((arena) { final message = "Simulated session error".toCharPtr(arena); @@ -452,13 +303,13 @@ class _RealmCore { } RealmHandle openRealm(Configuration config) { - final configHandle = _createConfig(config); + final configHandle = ConfigHandle(config); final realmPtr = invokeGetPointer(() => realmLib.realm_open(configHandle.pointer), "Error opening realm at path ${config.path}"); return RealmHandle._(realmPtr); } RealmAsyncOpenTaskHandle createRealmAsyncOpenTask(FlexibleSyncConfiguration config) { - final configHandle = _createConfig(config); + final configHandle = ConfigHandle(config); final asyncOpenTaskPtr = invokeGetPointer(() => realmLib.realm_open_synchronized(configHandle.pointer), "Error opening realm at path ${config.path}"); return RealmAsyncOpenTaskHandle._(asyncOpenTaskPtr); } @@ -2804,10 +2655,7 @@ class _RealmCore { }); } - void writeCopy(Realm realm, Configuration config) { - final configHandle = _createConfig(config); - invokeGetBool(() => realmLib.realm_convert_with_config(realm.handle.pointer, configHandle.pointer, false)); - } + void writeCopy(Realm realm, Configuration config) => realm.handle.writeCopy(config); void _createCollection(Realm realm, RealmValue value, Pointer Function() createList, Pointer Function() createMap) { CollectionHandleBase? collectionHandle; @@ -2869,10 +2717,6 @@ class SchemaHandle extends HandleBase { SchemaHandle.unowned(super.pointer) : super.unowned(); } -class ConfigHandle extends HandleBase { - ConfigHandle._(Pointer pointer) : super(pointer, 512); -} - class SchedulerHandle extends HandleBase { SchedulerHandle._(Pointer pointer) : super(pointer, 24); } diff --git a/packages/realm_dart/lib/src/native/realm_handle.dart b/packages/realm_dart/lib/src/native/realm_handle.dart index 0da17ef80..80aa7a9b7 100644 --- a/packages/realm_dart/lib/src/native/realm_handle.dart +++ b/packages/realm_dart/lib/src/native/realm_handle.dart @@ -72,7 +72,7 @@ class RealmHandle extends HandleBase { } void writeCopy(Configuration config) { - final configHandle = _RealmCore._createConfig(config); + final configHandle = ConfigHandle(config); invokeGetBool(() => realmLib.realm_convert_with_config(pointer, configHandle.pointer, false)); } } diff --git a/packages/realm_dart/lib/src/realm_class.dart b/packages/realm_dart/lib/src/realm_class.dart index 5f30f8dea..77cdfca19 100644 --- a/packages/realm_dart/lib/src/realm_class.dart +++ b/packages/realm_dart/lib/src/realm_class.dart @@ -84,7 +84,7 @@ export 'list.dart' show RealmList, RealmListOfObject, RealmListChanges, ListExte export 'logging.dart' hide RealmLoggerInternal; export 'map.dart' show RealmMap, RealmMapChanges, RealmMapOfObject; export 'migration.dart' show Migration; -export 'native/realm_core.dart' show Decimal128; +export 'native/realm_core.dart' show Decimal128, encryptionKeySize; export 'realm_object.dart' show AsymmetricObject, diff --git a/packages/realm_dart/test/configuration_test.dart b/packages/realm_dart/test/configuration_test.dart index aa512c948..5dbdf98eb 100644 --- a/packages/realm_dart/test/configuration_test.dart +++ b/packages/realm_dart/test/configuration_test.dart @@ -3,9 +3,10 @@ import 'dart:io'; import 'dart:math'; -import 'package:test/test.dart' hide test, throws; + import 'package:path/path.dart' as path; import 'package:realm_dart/realm.dart'; + import 'test.dart'; void main() { diff --git a/packages/realm_dart/test/realm_test.dart b/packages/realm_dart/test/realm_test.dart index 6d5a6e6d6..6625290ba 100644 --- a/packages/realm_dart/test/realm_test.dart +++ b/packages/realm_dart/test/realm_test.dart @@ -9,7 +9,6 @@ import 'dart:isolate'; import 'package:path/path.dart' as p; import 'package:realm_dart/realm.dart'; import 'package:realm_dart/src/native/realm_core.dart'; -import 'package:test/test.dart' hide test, throws; import 'package:timezone/data/latest.dart' as tz; import 'package:timezone/timezone.dart' as tz; diff --git a/packages/realm_dart/test/test.dart b/packages/realm_dart/test/test.dart index 4824679aa..12fe85cef 100644 --- a/packages/realm_dart/test/test.dart +++ b/packages/realm_dart/test/test.dart @@ -406,7 +406,6 @@ final _openRealms = Queue(); String testUsername = "realm-test@realm.io"; String testPassword = "123456"; -final int encryptionKeySize = 64; const int maxInt = 9223372036854775807; const int minInt = -9223372036854775808; From 9cb13370ed975057a46f8231a738870f27d7124f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Sat, 13 Apr 2024 12:42:10 +0200 Subject: [PATCH 16/68] Refactor _RealmQueryHandler (now QueryHandle) --- .../lib/src/native/config_handle.dart | 2 +- .../lib/src/native/query_handle.dart | 17 +++ .../realm_dart/lib/src/native/realm_core.dart | 123 ++---------------- .../lib/src/native/realm_handle.dart | 22 ++++ .../lib/src/native/schema_handle.dart | 74 +++++++++++ packages/realm_dart/lib/src/realm_class.dart | 7 +- 6 files changed, 129 insertions(+), 116 deletions(-) create mode 100644 packages/realm_dart/lib/src/native/query_handle.dart create mode 100644 packages/realm_dart/lib/src/native/schema_handle.dart diff --git a/packages/realm_dart/lib/src/native/config_handle.dart b/packages/realm_dart/lib/src/native/config_handle.dart index 85e619709..e3381463b 100644 --- a/packages/realm_dart/lib/src/native/config_handle.dart +++ b/packages/realm_dart/lib/src/native/config_handle.dart @@ -12,7 +12,7 @@ class ConfigHandle extends HandleBase { final configHandle = ConfigHandle._(configPtr); if (config.schemaObjects.isNotEmpty) { - final schemaHandle = _RealmCore._createSchema(config.schemaObjects); + final schemaHandle = SchemaHandle(config.schemaObjects); realmLib.realm_config_set_schema(configHandle.pointer, schemaHandle.pointer); } diff --git a/packages/realm_dart/lib/src/native/query_handle.dart b/packages/realm_dart/lib/src/native/query_handle.dart new file mode 100644 index 000000000..400dd6fa4 --- /dev/null +++ b/packages/realm_dart/lib/src/native/query_handle.dart @@ -0,0 +1,17 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + +part of 'realm_core.dart'; + +class QueryHandle extends RootedHandleBase { + QueryHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 256); + + RealmResultsHandle findAll() { + try { + final resultsPointer = invokeGetPointer(() => realmLib.realm_query_find_all(pointer)); + return RealmResultsHandle._(resultsPointer, _root); + } finally { + release(); + } + } +} diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index f2172f2ad..1959295bd 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -46,8 +46,10 @@ part 'convert.dart'; part 'decimal128.dart'; part 'error_handling.dart'; part 'mutable_subscription_set_handle.dart'; +part 'query_handle.dart'; part 'realm_handle.dart'; part 'rooted_handle.dart'; +part 'schema_handle.dart'; part 'subscription_handle.dart'; part 'subscription_set_handle.dart'; @@ -203,70 +205,6 @@ class _RealmCore { // realmLib.realm_dart_gc(); // } - static SchemaHandle _createSchema(Iterable schema) { - return using((Arena arena) { - final classCount = schema.length; - - final schemaClasses = arena(classCount); - final schemaProperties = arena>(classCount); - - for (var i = 0; i < classCount; i++) { - final schemaObject = schema.elementAt(i); - final classInfo = schemaClasses.elementAt(i).ref; - final propertiesCount = schemaObject.length; - final computedCount = schemaObject.where((p) => p.isComputed).length; - final persistedCount = propertiesCount - computedCount; - - classInfo.name = schemaObject.name.toCharPtr(arena); - classInfo.primary_key = "".toCharPtr(arena); - classInfo.num_properties = persistedCount; - classInfo.num_computed_properties = computedCount; - classInfo.key = RLM_INVALID_CLASS_KEY; - classInfo.flags = schemaObject.baseType.flags; - - final properties = arena(propertiesCount); - - for (var j = 0; j < propertiesCount; j++) { - final schemaProperty = schemaObject[j]; - final propInfo = properties.elementAt(j).ref; - propInfo.name = schemaProperty.mapTo.toCharPtr(arena); - propInfo.public_name = (schemaProperty.mapTo != schemaProperty.name ? schemaProperty.name : '').toCharPtr(arena); - propInfo.link_target = (schemaProperty.linkTarget ?? "").toCharPtr(arena); - propInfo.link_origin_property_name = (schemaProperty.linkOriginProperty ?? "").toCharPtr(arena); - propInfo.type = schemaProperty.propertyType.index; - propInfo.collection_type = schemaProperty.collectionType.index; - propInfo.flags = realm_property_flags.RLM_PROPERTY_NORMAL; - - if (schemaProperty.optional) { - propInfo.flags |= realm_property_flags.RLM_PROPERTY_NULLABLE; - } - - switch (schemaProperty.indexType) { - case RealmIndexType.regular: - propInfo.flags |= realm_property_flags.RLM_PROPERTY_INDEXED; - break; - case RealmIndexType.fullText: - propInfo.flags |= realm_property_flags.RLM_PROPERTY_FULLTEXT_INDEXED; - break; - default: - break; - } - - if (schemaProperty.primaryKey) { - classInfo.primary_key = schemaProperty.mapTo.toCharPtr(arena); - propInfo.flags |= realm_property_flags.RLM_PROPERTY_PRIMARY_KEY; - } - } - - schemaProperties[i] = properties; - schemaProperties.elementAt(i).value = properties; - } - - final schemaPtr = invokeGetPointer(() => realmLib.realm_schema_new(schemaClasses, classCount, schemaProperties)); - return SchemaHandle._(schemaPtr); - }); - } - String getPathForUser(User user) { final syncConfigPtr = invokeGetPointer(() => realmLib.realm_flx_sync_config_new(user.handle.pointer)); try { @@ -732,28 +670,6 @@ class _RealmCore { return RealmResultsHandle._(pointer, realm.handle); } - RealmResultsHandle queryClass(Realm realm, int classKey, String query, List args) { - return using((arena) { - final length = args.length; - final argsPointer = arena(length); - for (var i = 0; i < length; ++i) { - _intoRealmQueryArg(args[i], argsPointer.elementAt(i), arena); - } - final queryHandle = _RealmQueryHandle._( - invokeGetPointer( - () => realmLib.realm_query_parse( - realm.handle.pointer, - classKey, - query.toCharPtr(arena), - length, - argsPointer, - ), - ), - realm.handle); - return _queryFindAll(queryHandle); - }); - } - RealmResultsHandle queryResults(RealmResults target, String query, List args) { return using((arena) { final length = args.length; @@ -761,7 +677,7 @@ class _RealmCore { for (var i = 0; i < length; ++i) { _intoRealmQueryArg(args[i], argsPointer.elementAt(i), arena); } - final queryHandle = _RealmQueryHandle._( + final queryHandle = QueryHandle._( invokeGetPointer( () => realmLib.realm_query_parse_for_results( target.handle.pointer, @@ -771,19 +687,10 @@ class _RealmCore { ), ), target.realm.handle); - return _queryFindAll(queryHandle); + return queryHandle.findAll(); }); } - RealmResultsHandle _queryFindAll(_RealmQueryHandle queryHandle) { - try { - final resultsPointer = invokeGetPointer(() => realmLib.realm_query_find_all(queryHandle.pointer)); - return RealmResultsHandle._(resultsPointer, queryHandle._root); - } finally { - queryHandle.release(); - } - } - RealmResultsHandle queryList(RealmList target, String query, List args) { return using((arena) { final length = args.length; @@ -791,7 +698,7 @@ class _RealmCore { for (var i = 0; i < length; ++i) { _intoRealmQueryArg(args[i], argsPointer.elementAt(i), arena); } - final queryHandle = _RealmQueryHandle._( + final queryHandle = QueryHandle._( invokeGetPointer( () => realmLib.realm_query_parse_for_list( target.handle.pointer, @@ -801,7 +708,7 @@ class _RealmCore { ), ), target.realm.handle); - return _queryFindAll(queryHandle); + return queryHandle.findAll(); }); } @@ -812,7 +719,7 @@ class _RealmCore { for (var i = 0; i < length; ++i) { _intoRealmQueryArg(args[i], argsPointer.elementAt(i), arena); } - final queryHandle = _RealmQueryHandle._( + final queryHandle = QueryHandle._( invokeGetPointer( () => realmLib.realm_query_parse_for_set( target.handle.pointer, @@ -822,7 +729,7 @@ class _RealmCore { ), ), target.realm.handle); - return _queryFindAll(queryHandle); + return queryHandle.findAll(); }); } @@ -835,7 +742,7 @@ class _RealmCore { } final results = mapGetValues(target); - final queryHandle = _RealmQueryHandle._( + final queryHandle = QueryHandle._( invokeGetPointer( () => realmLib.realm_query_parse_for_results( results.pointer, @@ -845,7 +752,7 @@ class _RealmCore { ), ), target.realm.handle); - return _queryFindAll(queryHandle); + return queryHandle.findAll(); }); } @@ -2711,12 +2618,6 @@ class _RealmCore { } } -class SchemaHandle extends HandleBase { - SchemaHandle._(Pointer pointer) : super(pointer, 24); - - SchemaHandle.unowned(super.pointer) : super.unowned(); -} - class SchedulerHandle extends HandleBase { SchedulerHandle._(Pointer pointer) : super(pointer, 24); } @@ -2763,10 +2664,6 @@ class RealmMapHandle extends CollectionHandleBase { RealmMapHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 96); // TODO: check size } -class _RealmQueryHandle extends RootedHandleBase { - _RealmQueryHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 256); -} - class RealmCallbackTokenHandle extends RootedHandleBase { RealmCallbackTokenHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 32); } diff --git a/packages/realm_dart/lib/src/native/realm_handle.dart b/packages/realm_dart/lib/src/native/realm_handle.dart index 80aa7a9b7..c2831f6a8 100644 --- a/packages/realm_dart/lib/src/native/realm_handle.dart +++ b/packages/realm_dart/lib/src/native/realm_handle.dart @@ -75,4 +75,26 @@ class RealmHandle extends HandleBase { final configHandle = ConfigHandle(config); invokeGetBool(() => realmLib.realm_convert_with_config(pointer, configHandle.pointer, false)); } + + RealmResultsHandle queryClass(int classKey, String query, List args) { + return using((arena) { + final length = args.length; + final argsPointer = arena(length); + for (var i = 0; i < length; ++i) { + _intoRealmQueryArg(args[i], argsPointer.elementAt(i), arena); + } + final queryHandle = QueryHandle._( + invokeGetPointer( + () => realmLib.realm_query_parse( + pointer, + classKey, + query.toCharPtr(arena), + length, + argsPointer, + ), + ), + this); + return queryHandle.findAll(); + }); + } } diff --git a/packages/realm_dart/lib/src/native/schema_handle.dart b/packages/realm_dart/lib/src/native/schema_handle.dart new file mode 100644 index 000000000..c2afb6e16 --- /dev/null +++ b/packages/realm_dart/lib/src/native/schema_handle.dart @@ -0,0 +1,74 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + +part of 'realm_core.dart'; + +class SchemaHandle extends HandleBase { + SchemaHandle._(Pointer pointer) : super(pointer, 24); + + SchemaHandle.unowned(super.pointer) : super.unowned(); + + factory SchemaHandle(Iterable schema) { + return using((Arena arena) { + final classCount = schema.length; + + final schemaClasses = arena(classCount); + final schemaProperties = arena>(classCount); + + for (var i = 0; i < classCount; i++) { + final schemaObject = schema.elementAt(i); + final classInfo = schemaClasses.elementAt(i).ref; + final propertiesCount = schemaObject.length; + final computedCount = schemaObject.where((p) => p.isComputed).length; + final persistedCount = propertiesCount - computedCount; + + classInfo.name = schemaObject.name.toCharPtr(arena); + classInfo.primary_key = "".toCharPtr(arena); + classInfo.num_properties = persistedCount; + classInfo.num_computed_properties = computedCount; + classInfo.key = _RealmCore.RLM_INVALID_CLASS_KEY; + classInfo.flags = schemaObject.baseType.flags; + + final properties = arena(propertiesCount); + + for (var j = 0; j < propertiesCount; j++) { + final schemaProperty = schemaObject[j]; + final propInfo = properties.elementAt(j).ref; + propInfo.name = schemaProperty.mapTo.toCharPtr(arena); + propInfo.public_name = (schemaProperty.mapTo != schemaProperty.name ? schemaProperty.name : '').toCharPtr(arena); + propInfo.link_target = (schemaProperty.linkTarget ?? "").toCharPtr(arena); + propInfo.link_origin_property_name = (schemaProperty.linkOriginProperty ?? "").toCharPtr(arena); + propInfo.type = schemaProperty.propertyType.index; + propInfo.collection_type = schemaProperty.collectionType.index; + propInfo.flags = realm_property_flags.RLM_PROPERTY_NORMAL; + + if (schemaProperty.optional) { + propInfo.flags |= realm_property_flags.RLM_PROPERTY_NULLABLE; + } + + switch (schemaProperty.indexType) { + case RealmIndexType.regular: + propInfo.flags |= realm_property_flags.RLM_PROPERTY_INDEXED; + break; + case RealmIndexType.fullText: + propInfo.flags |= realm_property_flags.RLM_PROPERTY_FULLTEXT_INDEXED; + break; + default: + break; + } + + if (schemaProperty.primaryKey) { + classInfo.primary_key = schemaProperty.mapTo.toCharPtr(arena); + propInfo.flags |= realm_property_flags.RLM_PROPERTY_PRIMARY_KEY; + } + } + + schemaProperties[i] = properties; + schemaProperties.elementAt(i).value = properties; + } + + final schemaPtr = invokeGetPointer(() => realmLib.realm_schema_new(schemaClasses, classCount, schemaProperties)); + return SchemaHandle._(schemaPtr); + }); + } +} diff --git a/packages/realm_dart/lib/src/realm_class.dart b/packages/realm_dart/lib/src/realm_class.dart index 77cdfca19..31a45d91e 100644 --- a/packages/realm_dart/lib/src/realm_class.dart +++ b/packages/realm_dart/lib/src/realm_class.dart @@ -440,8 +440,11 @@ class Realm implements Finalizable { /// and [Predicate Programming Guide.](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Predicates/AdditionalChapters/Introduction.html#//apple_ref/doc/uid/TP40001789) RealmResults query(String query, [List args = const []]) { final metadata = _metadata.getByType(T); - final handle = realmCore.queryClass(this, metadata.classKey, query, args); - return RealmResultsInternal.create(handle, this, metadata); + return RealmResultsInternal.create( + _handle.queryClass(metadata.classKey, query, args), + this, + metadata, + ); } /// Deletes all [RealmObject]s of type `T` in the `Realm` From df00b0e6603022b1ace901b16a6b2ef96dc0a667 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Sat, 13 Apr 2024 12:57:46 +0200 Subject: [PATCH 17/68] Refactor RealmObjectHandle (now ObjectHandle) --- packages/realm_dart/lib/src/list.dart | 2 +- packages/realm_dart/lib/src/map.dart | 2 +- .../lib/src/native/object_handle.dart | 15 ++++ .../realm_dart/lib/src/native/realm_core.dart | 73 ++++++------------- .../lib/src/native/realm_handle.dart | 12 +-- packages/realm_dart/lib/src/realm_class.dart | 6 +- packages/realm_dart/lib/src/realm_object.dart | 10 +-- packages/realm_dart/lib/src/results.dart | 2 +- packages/realm_dart/lib/src/set.dart | 2 +- 9 files changed, 57 insertions(+), 67 deletions(-) create mode 100644 packages/realm_dart/lib/src/native/object_handle.dart diff --git a/packages/realm_dart/lib/src/list.dart b/packages/realm_dart/lib/src/list.dart index 41b4cb00f..34394d9cc 100644 --- a/packages/realm_dart/lib/src/list.dart +++ b/packages/realm_dart/lib/src/list.dart @@ -101,7 +101,7 @@ class ManagedRealmList with RealmEntity, ListMixin impleme try { var value = realmCore.listGetElementAt(this, index); - if (value is RealmObjectHandle) { + if (value is ObjectHandle) { late RealmObjectMetadata targetMetadata; late Type type; if (T == RealmValue) { diff --git a/packages/realm_dart/lib/src/map.dart b/packages/realm_dart/lib/src/map.dart index 29a8b92be..7264eb833 100644 --- a/packages/realm_dart/lib/src/map.dart +++ b/packages/realm_dart/lib/src/map.dart @@ -93,7 +93,7 @@ class ManagedRealmMap with RealmEntity, MapMixin i try { var value = realmCore.mapGetElement(this, key); - if (value is RealmObjectHandle) { + if (value is ObjectHandle) { late RealmObjectMetadata targetMetadata; late Type type; if (T == RealmValue) { diff --git a/packages/realm_dart/lib/src/native/object_handle.dart b/packages/realm_dart/lib/src/native/object_handle.dart new file mode 100644 index 000000000..6310f3f50 --- /dev/null +++ b/packages/realm_dart/lib/src/native/object_handle.dart @@ -0,0 +1,15 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + +part of 'realm_core.dart'; + +class ObjectHandle extends RootedHandleBase { + ObjectHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 112); + + ObjectHandle createEmbedded(int propertyKey) { + final objectPtr = invokeGetPointer(() => realmLib.realm_set_embedded(pointer, propertyKey)); + return ObjectHandle._(objectPtr, _root); + } + + int getClassKey() => realmLib.realm_object_get_table(pointer); +} diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 1959295bd..f43cc6901 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -46,6 +46,7 @@ part 'convert.dart'; part 'decimal128.dart'; part 'error_handling.dart'; part 'mutable_subscription_set_handle.dart'; +part 'object_handle.dart'; part 'query_handle.dart'; part 'realm_handle.dart'; part 'rooted_handle.dart'; @@ -573,31 +574,23 @@ class _RealmCore { return result; } - RealmObjectHandle createRealmObject(Realm realm, int classKey) => RealmObjectHandle.create(realm.handle, classKey); - - RealmObjectHandle createEmbeddedObject(RealmObjectBase obj, int propertyKey) => RealmObjectHandle.createEmbedded(obj.handle, propertyKey); - - Tuple getEmbeddedParent(EmbeddedObject obj) { + Tuple getEmbeddedParent(EmbeddedObject obj) { return using((Arena arena) { final parentPtr = arena>(); final classKeyPtr = arena(); invokeGetBool(() => realmLib.realm_object_get_parent(obj.handle.pointer, parentPtr, classKeyPtr)); - final handle = RealmObjectHandle._(parentPtr.value, obj.realm.handle); + final handle = ObjectHandle._(parentPtr.value, obj.realm.handle); return Tuple(handle, classKeyPtr.value); }); } + + ObjectHandle getOrCreateRealmObjectWithPrimaryKey(Realm realm, int classKey, Object? primaryKey) => + realm.handle.getOrCreateWithPrimaryKey(classKey, primaryKey); - int getClassKey(RealmObjectHandle handle) { - return realmLib.realm_object_get_table(handle.pointer); - } - - RealmObjectHandle getOrCreateRealmObjectWithPrimaryKey(Realm realm, int classKey, Object? primaryKey) => - RealmObjectHandle.getOrCreateWithPrimaryKey(realm.handle, classKey, primaryKey); - - RealmObjectHandle createRealmObjectWithPrimaryKey(Realm realm, int classKey, Object? primaryKey) => - RealmObjectHandle.createWithPrimaryKey(realm.handle, classKey, primaryKey); + ObjectHandle createRealmObjectWithPrimaryKey(Realm realm, int classKey, Object? primaryKey) => + realm.handle.createWithPrimaryKey(classKey, primaryKey); Object? getProperty(RealmObjectBase object, int propertyKey) { return using((Arena arena) { @@ -628,7 +621,7 @@ class _RealmCore { // ignore: unused_element int get _threadId => realmLib.realm_dart_get_thread_id(); - RealmObjectHandle? find(Realm realm, int classKey, Object? primaryKey) { + ObjectHandle? find(Realm realm, int classKey, Object? primaryKey) { return using((Arena arena) { final realm_value = _toRealmValue(primaryKey, arena); final pointer = realmLib.realm_object_find_with_primary_key(realm.handle.pointer, classKey, realm_value.ref, nullptr); @@ -636,14 +629,14 @@ class _RealmCore { return null; } - return RealmObjectHandle._(pointer, realm.handle); + return ObjectHandle._(pointer, realm.handle); }); } - RealmObjectHandle? findExisting(Realm realm, int classKey, RealmObjectHandle other) { + ObjectHandle? findExisting(Realm realm, int classKey, ObjectHandle other) { final key = realmLib.realm_object_get_key(other.pointer); final pointer = invokeGetPointer(() => realmLib.realm_get_object(realm.handle.pointer, classKey, key)); - return RealmObjectHandle._(pointer, realm.handle); + return ObjectHandle._(pointer, realm.handle); } void renameProperty(Realm realm, String objectType, String oldName, String newName, SchemaHandle schema) { @@ -794,9 +787,9 @@ class _RealmCore { }); } - RealmObjectHandle resultsGetObjectAt(RealmResults results, int index) { + ObjectHandle resultsGetObjectAt(RealmResults results, int index) { final pointer = invokeGetPointer(() => realmLib.realm_results_get_object(results.handle.pointer, index)); - return RealmObjectHandle._(pointer, results.realm.handle); + return ObjectHandle._(pointer, results.realm.handle); } int getResultsCount(RealmResults results) { @@ -921,9 +914,9 @@ class _RealmCore { return _RealmLinkHandle._(realmLink); } - RealmObjectHandle _getObject(Realm realm, int classKey, int objectKey) { + ObjectHandle _getObject(Realm realm, int classKey, int objectKey) { final pointer = invokeGetPointer(() => realmLib.realm_get_object(realm.handle.pointer, classKey, objectKey)); - return RealmObjectHandle._(pointer, realm.handle); + return ObjectHandle._(pointer, realm.handle); } RealmListHandle getListProperty(RealmObjectBase object, int propertyKey) { @@ -965,14 +958,14 @@ class _RealmCore { () => (insert ? realmLib.realm_list_insert_dictionary : realmLib.realm_list_set_dictionary)(handle.pointer, index)); } - RealmObjectHandle listSetEmbeddedObjectAt(Realm realm, RealmListHandle handle, int index) { + ObjectHandle listSetEmbeddedObjectAt(Realm realm, RealmListHandle handle, int index) { final ptr = invokeGetPointer(() => realmLib.realm_list_set_embedded(handle.pointer, index)); - return RealmObjectHandle._(ptr, realm.handle); + return ObjectHandle._(ptr, realm.handle); } - RealmObjectHandle listInsertEmbeddedObjectAt(Realm realm, RealmListHandle handle, int index) { + ObjectHandle listInsertEmbeddedObjectAt(Realm realm, RealmListHandle handle, int index) { final ptr = invokeGetPointer(() => realmLib.realm_list_insert_embedded(handle.pointer, index)); - return RealmObjectHandle._(ptr, realm.handle); + return ObjectHandle._(ptr, realm.handle); } void listRemoveElementAt(RealmListHandle handle, int index) { @@ -1165,11 +1158,11 @@ class _RealmCore { }); } - RealmObjectHandle mapInsertEmbeddedObject(Realm realm, RealmMapHandle handle, String key) { + ObjectHandle mapInsertEmbeddedObject(Realm realm, RealmMapHandle handle, String key) { return using((Arena arena) { final realm_value = _toRealmValue(key, arena); final ptr = invokeGetPointer(() => realmLib.realm_dictionary_insert_embedded(handle.pointer, realm_value.ref)); - return RealmObjectHandle._(ptr, realm.handle); + return ObjectHandle._(ptr, realm.handle); }); } @@ -2296,11 +2289,11 @@ class _RealmCore { return RealmResultsHandle._(ptr, frozenRealm.handle); } - RealmObjectHandle? resolveObject(RealmObjectBase object, Realm frozenRealm) { + ObjectHandle? resolveObject(RealmObjectBase object, Realm frozenRealm) { return using((Arena arena) { final resultPtr = arena>(); invokeGetBool(() => realmLib.realm_object_resolve_in(object.handle.pointer, frozenRealm.handle.pointer, resultPtr)); - return resultPtr == nullptr ? null : RealmObjectHandle._(resultPtr.value, frozenRealm.handle); + return resultPtr == nullptr ? null : ObjectHandle._(resultPtr.value, frozenRealm.handle); }); } @@ -2622,24 +2615,6 @@ class SchedulerHandle extends HandleBase { SchedulerHandle._(Pointer pointer) : super(pointer, 24); } -class RealmObjectHandle extends RootedHandleBase { - RealmObjectHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 112); - - factory RealmObjectHandle.createWithPrimaryKey(RealmHandle realm, int classKey, Object? primaryKey) => realm.createWithPrimaryKey(classKey, primaryKey); - - factory RealmObjectHandle.create(RealmHandle realm, int classKey) => realm.create(classKey); - - factory RealmObjectHandle.createEmbedded(RealmObjectHandle parent, int propertyKey) => parent.createEmbedded(propertyKey); - - RealmObjectHandle createEmbedded(int propertyKey) { - final objectPtr = invokeGetPointer(() => realmLib.realm_set_embedded(pointer, propertyKey)); - return RealmObjectHandle._(objectPtr, _root); - } - - factory RealmObjectHandle.getOrCreateWithPrimaryKey(RealmHandle realm, int classKey, Object? primaryKey) => - realm.getOrCreateWithPrimaryKey(classKey, primaryKey); -} - class _RealmLinkHandle { final int targetKey; final int classKey; diff --git a/packages/realm_dart/lib/src/native/realm_handle.dart b/packages/realm_dart/lib/src/native/realm_handle.dart index c2831f6a8..bfd9df79d 100644 --- a/packages/realm_dart/lib/src/native/realm_handle.dart +++ b/packages/realm_dart/lib/src/native/realm_handle.dart @@ -36,20 +36,20 @@ class RealmHandle extends HandleBase { } } - RealmObjectHandle createWithPrimaryKey(int classKey, Object? primaryKey) { + ObjectHandle createWithPrimaryKey(int classKey, Object? primaryKey) { return using((Arena arena) { final realmValue = _toRealmValue(primaryKey, arena); final realmPtr = invokeGetPointer(() => realmLib.realm_object_create_with_primary_key(pointer, classKey, realmValue.ref)); - return RealmObjectHandle._(realmPtr, this); + return ObjectHandle._(realmPtr, this); }); } - RealmObjectHandle create(int classKey) { + ObjectHandle create(int classKey) { final realmPtr = invokeGetPointer(() => realmLib.realm_object_create(pointer, classKey)); - return RealmObjectHandle._(realmPtr, this); + return ObjectHandle._(realmPtr, this); } - RealmObjectHandle getOrCreateWithPrimaryKey(int classKey, Object? primaryKey) { + ObjectHandle getOrCreateWithPrimaryKey(int classKey, Object? primaryKey) { return using((Arena arena) { final realmValue = _toRealmValue(primaryKey, arena); final didCreate = arena(); @@ -59,7 +59,7 @@ class RealmHandle extends HandleBase { realmValue.ref, didCreate, )); - return RealmObjectHandle._(realmPtr, this); + return ObjectHandle._(realmPtr, this); }); } diff --git a/packages/realm_dart/lib/src/realm_class.dart b/packages/realm_dart/lib/src/realm_class.dart index 31a45d91e..b454c30ff 100644 --- a/packages/realm_dart/lib/src/realm_class.dart +++ b/packages/realm_dart/lib/src/realm_class.dart @@ -283,7 +283,7 @@ class Realm implements Finalizable { object.manage(this, handle, accessor, false); } - RealmObjectHandle _createObject(RealmObjectBase object, RealmObjectMetadata metadata, bool update) { + ObjectHandle _createObject(RealmObjectBase object, RealmObjectMetadata metadata, bool update) { final key = metadata.classKey; final primaryKey = metadata.primaryKey; if (primaryKey == null) { @@ -737,7 +737,7 @@ extension RealmInternal on Realm { return Realm._(config, handle, isInMigration); } - RealmObjectBase createObject(Type type, RealmObjectHandle handle, RealmObjectMetadata metadata) { + RealmObjectBase createObject(Type type, ObjectHandle handle, RealmObjectMetadata metadata) { final accessor = RealmCoreAccessor(metadata, _isInMigration); return RealmObjectInternal.create(type, this, handle, accessor); } @@ -768,7 +768,7 @@ extension RealmInternal on Realm { RealmMetadata get metadata => _metadata; - void manageEmbedded(RealmObjectHandle handle, EmbeddedObject object, {bool update = false}) { + void manageEmbedded(ObjectHandle handle, EmbeddedObject object, {bool update = false}) { final metadata = _metadata.getByType(object.runtimeType); final accessor = RealmCoreAccessor(metadata, _isInMigration); diff --git a/packages/realm_dart/lib/src/realm_object.dart b/packages/realm_dart/lib/src/realm_object.dart index 8218f9850..bf9d35e06 100644 --- a/packages/realm_dart/lib/src/realm_object.dart +++ b/packages/realm_dart/lib/src/realm_object.dart @@ -229,7 +229,7 @@ class RealmCoreAccessor implements RealmAccessor { default: var value = realmCore.getProperty(object, propertyMeta.key); - if (value is RealmObjectHandle) { + if (value is ObjectHandle) { final meta = object.realm.metadata; final typeName = propertyMeta.objectType; @@ -365,7 +365,7 @@ extension RealmEntityInternal on RealmEntity { /// [RealmObject] should not be used directly as it is part of the generated class hierarchy. ex: `MyClass extends _MyClass with RealmObject`. /// {@category Realm} mixin RealmObjectBase on RealmEntity implements RealmObjectBaseMarker, Finalizable { - RealmObjectHandle? _handle; + ObjectHandle? _handle; RealmAccessor _accessor = RealmValuesAccessor(); static final Map _factories = { // Register default factories for `RealmObject` and `RealmObject?`. Whenever the user @@ -651,7 +651,7 @@ extension RealmObjectInternal on RealmObjectBase { _handle?.keepAlive(); } - void manage(Realm realm, RealmObjectHandle handle, RealmCoreAccessor accessor, bool update) { + void manage(Realm realm, ObjectHandle handle, RealmCoreAccessor accessor, bool update) { if (_handle != null) { //most certainly a bug hence we throw an Error throw ArgumentError("Object is already managed"); @@ -667,7 +667,7 @@ extension RealmObjectInternal on RealmObjectBase { _accessor = accessor; } - static RealmObjectBase create(Type type, Realm realm, RealmObjectHandle handle, RealmCoreAccessor accessor) { + static RealmObjectBase create(Type type, Realm realm, ObjectHandle handle, RealmCoreAccessor accessor) { final object = RealmObjectBase.createObject(type, accessor.metadata); object._handle = handle; object._accessor = accessor; @@ -675,7 +675,7 @@ extension RealmObjectInternal on RealmObjectBase { return object; } - RealmObjectHandle get handle { + ObjectHandle get handle { if (_handle?.released == true) { throw RealmClosedError('Cannot access an object that belongs to a closed Realm'); } diff --git a/packages/realm_dart/lib/src/results.dart b/packages/realm_dart/lib/src/results.dart index a3f816161..554b09a24 100644 --- a/packages/realm_dart/lib/src/results.dart +++ b/packages/realm_dart/lib/src/results.dart @@ -44,7 +44,7 @@ class RealmResults extends Iterable with RealmEntity imple var value = realmCore.resultsGetElementAt(this, _skipOffset + index); - if (value is RealmObjectHandle) { + if (value is ObjectHandle) { late RealmObjectMetadata targetMetadata; late Type type; if (T == RealmValue) { diff --git a/packages/realm_dart/lib/src/set.dart b/packages/realm_dart/lib/src/set.dart index ce79e1f7e..700629130 100644 --- a/packages/realm_dart/lib/src/set.dart +++ b/packages/realm_dart/lib/src/set.dart @@ -157,7 +157,7 @@ class ManagedRealmSet with RealmEntity, SetMixin implement try { var value = realmCore.realmSetGetElementAt(this, index); - if (value is RealmObjectHandle) { + if (value is ObjectHandle) { late RealmObjectMetadata targetMetadata; late Type type; if (T == RealmValue) { From 03b864f78347a9e460f0f0e5aeb270e13f612f45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Sat, 13 Apr 2024 13:55:39 +0200 Subject: [PATCH 18/68] Refactor RealmResultHandle (now ResultsHandle) --- packages/realm_dart/lib/src/list.dart | 2 +- packages/realm_dart/lib/src/map.dart | 2 +- .../lib/src/native/query_handle.dart | 4 +- .../realm_dart/lib/src/native/realm_core.dart | 122 +++--------------- .../lib/src/native/realm_handle.dart | 4 +- .../lib/src/native/results_handle.dart | 94 ++++++++++++++ packages/realm_dart/lib/src/realm_class.dart | 6 +- packages/realm_dart/lib/src/realm_object.dart | 4 +- packages/realm_dart/lib/src/results.dart | 18 +-- packages/realm_dart/lib/src/set.dart | 2 +- 10 files changed, 136 insertions(+), 122 deletions(-) create mode 100644 packages/realm_dart/lib/src/native/results_handle.dart diff --git a/packages/realm_dart/lib/src/list.dart b/packages/realm_dart/lib/src/list.dart index 34394d9cc..313fae091 100644 --- a/packages/realm_dart/lib/src/list.dart +++ b/packages/realm_dart/lib/src/list.dart @@ -105,7 +105,7 @@ class ManagedRealmList with RealmEntity, ListMixin impleme late RealmObjectMetadata targetMetadata; late Type type; if (T == RealmValue) { - (type, targetMetadata) = realm.metadata.getByClassKey(realmCore.getClassKey(value)); + (type, targetMetadata) = realm.metadata.getByClassKey(value.getClassKey()); } else { targetMetadata = _metadata!; type = T; diff --git a/packages/realm_dart/lib/src/map.dart b/packages/realm_dart/lib/src/map.dart index 7264eb833..33f5636ec 100644 --- a/packages/realm_dart/lib/src/map.dart +++ b/packages/realm_dart/lib/src/map.dart @@ -97,7 +97,7 @@ class ManagedRealmMap with RealmEntity, MapMixin i late RealmObjectMetadata targetMetadata; late Type type; if (T == RealmValue) { - (type, targetMetadata) = realm.metadata.getByClassKey(realmCore.getClassKey(value)); + (type, targetMetadata) = realm.metadata.getByClassKey(value.getClassKey()); } else { targetMetadata = _metadata!; type = T; diff --git a/packages/realm_dart/lib/src/native/query_handle.dart b/packages/realm_dart/lib/src/native/query_handle.dart index 400dd6fa4..e2e2dea5a 100644 --- a/packages/realm_dart/lib/src/native/query_handle.dart +++ b/packages/realm_dart/lib/src/native/query_handle.dart @@ -6,10 +6,10 @@ part of 'realm_core.dart'; class QueryHandle extends RootedHandleBase { QueryHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 256); - RealmResultsHandle findAll() { + ResultsHandle findAll() { try { final resultsPointer = invokeGetPointer(() => realmLib.realm_query_find_all(pointer)); - return RealmResultsHandle._(resultsPointer, _root); + return ResultsHandle._(resultsPointer, _root); } finally { release(); } diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index f43cc6901..3b70146fa 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -49,6 +49,7 @@ part 'mutable_subscription_set_handle.dart'; part 'object_handle.dart'; part 'query_handle.dart'; part 'realm_handle.dart'; +part 'results_handle.dart'; part 'rooted_handle.dart'; part 'schema_handle.dart'; part 'subscription_handle.dart'; @@ -585,12 +586,11 @@ class _RealmCore { return Tuple(handle, classKeyPtr.value); }); } - + ObjectHandle getOrCreateRealmObjectWithPrimaryKey(Realm realm, int classKey, Object? primaryKey) => realm.handle.getOrCreateWithPrimaryKey(classKey, primaryKey); - ObjectHandle createRealmObjectWithPrimaryKey(Realm realm, int classKey, Object? primaryKey) => - realm.handle.createWithPrimaryKey(classKey, primaryKey); + ObjectHandle createRealmObjectWithPrimaryKey(Realm realm, int classKey, Object? primaryKey) => realm.handle.createWithPrimaryKey(classKey, primaryKey); Object? getProperty(RealmObjectBase object, int propertyKey) { return using((Arena arena) { @@ -658,33 +658,12 @@ class _RealmCore { invokeGetBool(() => realmLib.realm_object_delete(object.handle.pointer)); } - RealmResultsHandle findAll(Realm realm, int classKey) { + ResultsHandle findAll(Realm realm, int classKey) { final pointer = invokeGetPointer(() => realmLib.realm_object_find_all(realm.handle.pointer, classKey)); - return RealmResultsHandle._(pointer, realm.handle); - } - - RealmResultsHandle queryResults(RealmResults target, String query, List args) { - return using((arena) { - final length = args.length; - final argsPointer = arena(length); - for (var i = 0; i < length; ++i) { - _intoRealmQueryArg(args[i], argsPointer.elementAt(i), arena); - } - final queryHandle = QueryHandle._( - invokeGetPointer( - () => realmLib.realm_query_parse_for_results( - target.handle.pointer, - query.toCharPtr(arena), - length, - argsPointer, - ), - ), - target.realm.handle); - return queryHandle.findAll(); - }); + return ResultsHandle._(pointer, realm.handle); } - RealmResultsHandle queryList(RealmList target, String query, List args) { + ResultsHandle queryList(RealmList target, String query, List args) { return using((arena) { final length = args.length; final argsPointer = arena(length); @@ -705,7 +684,7 @@ class _RealmCore { }); } - RealmResultsHandle querySet(RealmSet target, String query, List args) { + ResultsHandle querySet(RealmSet target, String query, List args) { return using((arena) { final length = args.length; final argsPointer = arena(length); @@ -726,7 +705,7 @@ class _RealmCore { }); } - RealmResultsHandle queryMap(ManagedRealmMap target, String query, List args) { + ResultsHandle queryMap(ManagedRealmMap target, String query, List args) { return using((arena) { final length = args.length; final argsPointer = arena(length); @@ -749,14 +728,14 @@ class _RealmCore { }); } - RealmResultsHandle resultsFromList(RealmList list) { + ResultsHandle resultsFromList(RealmList list) { final pointer = invokeGetPointer(() => realmLib.realm_list_to_results(list.handle.pointer)); - return RealmResultsHandle._(pointer, list.realm.handle); + return ResultsHandle._(pointer, list.realm.handle); } - RealmResultsHandle resultsFromSet(RealmSet set) { + ResultsHandle resultsFromSet(RealmSet set) { final pointer = invokeGetPointer(() => realmLib.realm_set_to_results(set.handle.pointer)); - return RealmResultsHandle._(pointer, set.realm.handle); + return ResultsHandle._(pointer, set.realm.handle); } Object? resultsGetElementAt(RealmResults results, int index) { @@ -768,46 +747,6 @@ class _RealmCore { }); } - int resultsFind(RealmResults results, Object? value) { - return using((Arena arena) { - final out_index = arena(); - final out_found = arena(); - - // TODO: how should this behave for collections - final realm_value = _toRealmValue(value, arena); - invokeGetBool( - () => realmLib.realm_results_find( - results.handle.pointer, - realm_value, - out_index, - out_found, - ), - ); - return out_found.value ? out_index.value : -1; - }); - } - - ObjectHandle resultsGetObjectAt(RealmResults results, int index) { - final pointer = invokeGetPointer(() => realmLib.realm_results_get_object(results.handle.pointer, index)); - return ObjectHandle._(pointer, results.realm.handle); - } - - int getResultsCount(RealmResults results) { - return using((Arena arena) { - final countPtr = arena(); - invokeGetBool(() => realmLib.realm_results_count(results.handle.pointer, countPtr)); - return countPtr.value; - }); - } - - bool resultsIsValid(RealmResults results) { - return using((arena) { - final is_valid = arena(); - invokeGetBool(() => realmLib.realm_results_is_valid(results.handle.pointer, is_valid)); - return is_valid.value; - }); - } - CollectionChanges getCollectionChanges(RealmCollectionChangesHandle changes) { return using((arena) { final out_num_deletions = arena(); @@ -924,9 +863,9 @@ class _RealmCore { return RealmListHandle._(pointer, object.realm.handle); } - RealmResultsHandle getBacklinks(RealmObjectBase object, int sourceTableKey, int propertyKey) { + ResultsHandle getBacklinks(RealmObjectBase object, int sourceTableKey, int propertyKey) { final pointer = invokeGetPointer(() => realmLib.realm_get_backlinks(object.handle.pointer, sourceTableKey, propertyKey)); - return RealmResultsHandle._(pointer, object.realm.handle); + return ResultsHandle._(pointer, object.realm.handle); } int getListSize(RealmListHandle handle) { @@ -999,10 +938,6 @@ class _RealmCore { }); } - void resultsDeleteAll(RealmResults results) { - invokeGetBool(() => realmLib.realm_results_delete_all(results.handle.pointer)); - } - void listClear(RealmListHandle listHandle) { invokeGetBool(() => realmLib.realm_list_clear(listHandle.pointer)); } @@ -1125,18 +1060,18 @@ class _RealmCore { invokeGetBool(() => realmLib.realm_dictionary_clear(mapHandle.pointer)); } - RealmResultsHandle mapGetKeys(ManagedRealmMap map) { + ResultsHandle mapGetKeys(ManagedRealmMap map) { return using((Arena arena) { final out_size = arena(); final out_keys = arena>(); invokeGetBool(() => realmLib.realm_dictionary_get_keys(map.handle.pointer, out_size, out_keys)); - return RealmResultsHandle._(out_keys.value, map.realm.handle); + return ResultsHandle._(out_keys.value, map.realm.handle); }); } - RealmResultsHandle mapGetValues(ManagedRealmMap map) { + ResultsHandle mapGetValues(ManagedRealmMap map) { final result = invokeGetPointer(() => realmLib.realm_dictionary_to_results(map.handle.pointer)); - return RealmResultsHandle._(result, map.realm.handle); + return ResultsHandle._(result, map.realm.handle); } bool mapContainsKey(ManagedRealmMap map, String key) { @@ -1204,11 +1139,6 @@ class _RealmCore { return hashCode; } - RealmResultsHandle resultsSnapshot(RealmResults results) { - final resultsPointer = invokeGetPointer(() => realmLib.realm_results_snapshot(results.handle.pointer)); - return RealmResultsHandle._(resultsPointer, results.realm.handle); - } - bool objectIsValid(RealmObjectBase object) { return realmLib.realm_object_is_valid(object.handle.pointer); } @@ -2279,16 +2209,8 @@ class _RealmCore { return realmLib.realm_is_frozen(realm.handle.pointer.cast()); } - RealmHandle freeze(Realm realm) { - final ptr = invokeGetPointer(() => realmLib.realm_freeze(realm.handle.pointer)); - return RealmHandle._(ptr); - } - - RealmResultsHandle resolveResults(RealmResults realmResults, Realm frozenRealm) { - final ptr = invokeGetPointer(() => realmLib.realm_results_resolve_in(realmResults.handle.pointer, frozenRealm.handle.pointer)); - return RealmResultsHandle._(ptr, frozenRealm.handle); - } - + ResultsHandle resolveResults(RealmResults realmResults, Realm frozenRealm) => realmResults.handle.resolveIn(frozenRealm.handle); + ObjectHandle? resolveObject(RealmObjectBase object, Realm frozenRealm) { return using((Arena arena) { final resultPtr = arena>(); @@ -2623,10 +2545,6 @@ class _RealmLinkHandle { classKey = link.target_table; } -class RealmResultsHandle extends RootedHandleBase { - RealmResultsHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 872); -} - class RealmListHandle extends CollectionHandleBase { RealmListHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 88); } diff --git a/packages/realm_dart/lib/src/native/realm_handle.dart b/packages/realm_dart/lib/src/native/realm_handle.dart index bfd9df79d..1a8039e0d 100644 --- a/packages/realm_dart/lib/src/native/realm_handle.dart +++ b/packages/realm_dart/lib/src/native/realm_handle.dart @@ -76,7 +76,7 @@ class RealmHandle extends HandleBase { invokeGetBool(() => realmLib.realm_convert_with_config(pointer, configHandle.pointer, false)); } - RealmResultsHandle queryClass(int classKey, String query, List args) { + ResultsHandle queryClass(int classKey, String query, List args) { return using((arena) { final length = args.length; final argsPointer = arena(length); @@ -97,4 +97,6 @@ class RealmHandle extends HandleBase { return queryHandle.findAll(); }); } + + RealmHandle freeze() => RealmHandle._(invokeGetPointer(() => realmLib.realm_freeze(pointer))); } diff --git a/packages/realm_dart/lib/src/native/results_handle.dart b/packages/realm_dart/lib/src/native/results_handle.dart new file mode 100644 index 000000000..27c41a8ec --- /dev/null +++ b/packages/realm_dart/lib/src/native/results_handle.dart @@ -0,0 +1,94 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + +part of 'realm_core.dart'; + +class ResultsHandle extends RootedHandleBase { + ResultsHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 872); + + ResultsHandle queryResults(String query, List args) { + return using((arena) { + final length = args.length; + final argsPointer = arena(length); + for (var i = 0; i < length; ++i) { + _intoRealmQueryArg(args[i], argsPointer.elementAt(i), arena); + } + final queryHandle = QueryHandle._( + invokeGetPointer( + () => realmLib.realm_query_parse_for_results( + pointer, + query.toCharPtr(arena), + length, + argsPointer, + ), + ), + _root); + return queryHandle.findAll(); + }); + } + + int find(Object? value) { + return using((Arena arena) { + final outIndex = arena(); + final outFound = arena(); + + // TODO: how should this behave for collections + final realmValue = _toRealmValue(value, arena); + invokeGetBool( + () => realmLib.realm_results_find( + pointer, + realmValue, + outIndex, + outFound, + ), + ); + return outFound.value ? outIndex.value : -1; + }); + } + + ObjectHandle getObjectAt(int index) { + final objectPointer = invokeGetPointer(() => realmLib.realm_results_get_object(pointer, index)); + return ObjectHandle._(objectPointer, _root); + } + + int get count { + return using((Arena arena) { + final countPtr = arena(); + invokeGetBool(() => realmLib.realm_results_count(pointer, countPtr)); + return countPtr.value; + }); + } + + bool isValid() { + return using((arena) { + final isValid = arena(); + invokeGetBool(() => realmLib.realm_results_is_valid(pointer, isValid)); + return isValid.value; + }); + } + + void deleteAll() { + invokeGetBool(() => realmLib.realm_results_delete_all(pointer)); + } + + ResultsHandle snapshot() { + final resultsPointer = invokeGetPointer(() => realmLib.realm_results_snapshot(pointer)); + return ResultsHandle._(resultsPointer, _root); + } + + ResultsHandle resolveIn(RealmHandle realmHandle) { + final ptr = invokeGetPointer(() => realmLib.realm_results_resolve_in(pointer, realmHandle.pointer)); + return ResultsHandle._(ptr, realmHandle); + } + +/* + Object? resultsGetElementAt(int index) { + return using((Arena arena) { + final realmValue = arena(); + invokeGetBool(() => realmLib.realm_results_get(pointer, index, realmValue)); + return realmValue.toDartValue(results.realm, () => realmLib.realm_results_get_list(pointer, index), + () => realmLib.realm_results_get_dictionary(pointer, index)); + }); + } +*/ +} diff --git a/packages/realm_dart/lib/src/realm_class.dart b/packages/realm_dart/lib/src/realm_class.dart index b454c30ff..bdc3cd4a4 100644 --- a/packages/realm_dart/lib/src/realm_class.dart +++ b/packages/realm_dart/lib/src/realm_class.dart @@ -287,7 +287,7 @@ class Realm implements Finalizable { final key = metadata.classKey; final primaryKey = metadata.primaryKey; if (primaryKey == null) { - return realmCore.createRealmObject(this, key); + return this.handle.create(key); } if (update) { return realmCore.getOrCreateRealmObjectWithPrimaryKey(this, key, object.accessor.get(object, primaryKey)); @@ -328,7 +328,7 @@ class Realm implements Finalizable { if (items is RealmResults) { _ensureManagedByThis(items, 'delete objects from Realm'); - realmCore.resultsDeleteAll(items); + items.handle.deleteAll(); } else if (items is ManagedRealmList) { _ensureManagedByThis(items, 'delete objects from Realm'); @@ -466,7 +466,7 @@ class Realm implements Finalizable { return this; } - return Realm._(config, realmCore.freeze(this)); + return Realm._(config, this.handle.freeze()); } WeakReference? _subscriptions; diff --git a/packages/realm_dart/lib/src/realm_object.dart b/packages/realm_dart/lib/src/realm_object.dart index bf9d35e06..d03217aa7 100644 --- a/packages/realm_dart/lib/src/realm_object.dart +++ b/packages/realm_dart/lib/src/realm_object.dart @@ -237,7 +237,7 @@ class RealmCoreAccessor implements RealmAccessor { late RealmObjectMetadata targetMetadata; if (propertyMeta.propertyType == RealmPropertyType.mixed) { - (type, targetMetadata) = meta.getByClassKey(realmCore.getClassKey(value)); + (type, targetMetadata) = meta.getByClassKey(value.getClassKey()); } else { // If we have an object but the user called the API without providing a generic // arg, we construct a RealmObject since we don't know the type of the object. @@ -318,7 +318,7 @@ class RealmCoreAccessor implements RealmAccessor { throw RealmError("Can't set an embedded object that is already managed"); } - final handle = realmCore.createEmbeddedObject(object, propertyMeta.key); + final handle = object.handle.createEmbedded(propertyMeta.key); object.realm.manageEmbedded(handle, value, update: update); return; } diff --git a/packages/realm_dart/lib/src/results.dart b/packages/realm_dart/lib/src/results.dart index 554b09a24..8d2f54ef8 100644 --- a/packages/realm_dart/lib/src/results.dart +++ b/packages/realm_dart/lib/src/results.dart @@ -18,7 +18,7 @@ import 'realm_object.dart'; /// {@category Realm} class RealmResults extends Iterable with RealmEntity implements Finalizable { final RealmObjectMetadata? _metadata; - final RealmResultsHandle _handle; + final ResultsHandle _handle; final int _skipOffset; // to support skip efficiently final _supportsSnapshot = [] is List; @@ -29,7 +29,7 @@ class RealmResults extends Iterable with RealmEntity imple } /// Gets a value indicating whether this collection is still valid to use. - bool get isValid => realmCore.resultsIsValid(this); + bool get isValid => this.handle.isValid(); /// Returns the element of type `T` at the specified [index]. T operator [](int index) => elementAt(index); @@ -48,7 +48,7 @@ class RealmResults extends Iterable with RealmEntity imple late RealmObjectMetadata targetMetadata; late Type type; if (T == RealmValue) { - (type, targetMetadata) = realm.metadata.getByClassKey(realmCore.getClassKey(value)); + (type, targetMetadata) = realm.metadata.getByClassKey(value.getClassKey()); } else { targetMetadata = _metadata!; type = T; @@ -81,7 +81,7 @@ class RealmResults extends Iterable with RealmEntity imple if (start < 0) start = 0; start += _skipOffset; - final index = realmCore.resultsFind(this, element); + final index = this.handle.find(element); return index < start ? -1 : index; // to align with dart list semantics } @@ -102,7 +102,7 @@ class RealmResults extends Iterable with RealmEntity imple Iterator get iterator { var results = this; if (_supportsSnapshot) { - final handle = realmCore.resultsSnapshot(this); + final handle = this.handle.snapshot(); results = RealmResultsInternal.create(handle, realm, _metadata, _skipOffset); } return _RealmResultsIterator(results); @@ -110,7 +110,7 @@ class RealmResults extends Iterable with RealmEntity imple /// The number of values in this `Results` collection. @override - int get length => realmCore.getResultsCount(this) - _skipOffset; + int get length => this.handle.count - _skipOffset; @override T get first { @@ -174,7 +174,7 @@ extension RealmResultsOfObject on RealmResults { /// /// The Realm Dart and Realm Flutter SDKs supports querying based on a language inspired by [NSPredicate](https://www.mongodb.com/docs/realm/realm-query-language/) RealmResults query(String query, [List args = const []]) { - final handle = realmCore.queryResults(this, query, args); + final handle = this.handle.queryResults(query, args); return RealmResultsInternal.create(handle, realm, _metadata); } } @@ -280,7 +280,7 @@ extension RealmResultsInternal on RealmResults { _handle.keepAlive(); } - RealmResultsHandle get handle { + ResultsHandle get handle { if (_handle.released) { throw RealmClosedError('Cannot access Results that belongs to a closed Realm'); } @@ -290,7 +290,7 @@ extension RealmResultsInternal on RealmResults { RealmObjectMetadata get metadata => _metadata!; - static RealmResults create(RealmResultsHandle handle, Realm realm, RealmObjectMetadata? metadata, [int skip = 0]) => + static RealmResults create(ResultsHandle handle, Realm realm, RealmObjectMetadata? metadata, [int skip = 0]) => RealmResults._(handle, realm, metadata, skip); } diff --git a/packages/realm_dart/lib/src/set.dart b/packages/realm_dart/lib/src/set.dart index 700629130..eb8fc4756 100644 --- a/packages/realm_dart/lib/src/set.dart +++ b/packages/realm_dart/lib/src/set.dart @@ -161,7 +161,7 @@ class ManagedRealmSet with RealmEntity, SetMixin implement late RealmObjectMetadata targetMetadata; late Type type; if (T == RealmValue) { - (type, targetMetadata) = realm.metadata.getByClassKey(realmCore.getClassKey(value)); + (type, targetMetadata) = realm.metadata.getByClassKey(value.getClassKey()); } else { targetMetadata = _metadata!; // will be null for RealmValue, so defer until here type = T; From 789eb6109c2b3d84d1a2905ffd187efdd62f45bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Sat, 13 Apr 2024 14:26:24 +0200 Subject: [PATCH 19/68] More RealmHandle stuff --- .../realm_dart/lib/src/native/realm_core.dart | 147 +----------------- .../lib/src/native/realm_handle.dart | 141 +++++++++++++++++ packages/realm_dart/lib/src/realm_class.dart | 32 ++-- packages/realm_dart/test/realm_test.dart | 2 +- 4 files changed, 160 insertions(+), 162 deletions(-) diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 3b70146fa..f8ad5dc3f 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -217,10 +217,6 @@ class _RealmCore { } } - SubscriptionSetHandle getSubscriptions(Realm realm) { - return SubscriptionSetHandle._(invokeGetPointer(() => realmLib.realm_sync_get_active_subscription_set(realm.handle.pointer)), realm.handle); - } - void raiseError(Session session, int errorCode, bool isFatal) { using((arena) { final message = "Simulated session error".toCharPtr(arena); @@ -228,10 +224,6 @@ class _RealmCore { }); } - void realmDisableAutoRefreshForTesting(Realm realm) { - realmLib.realm_set_auto_refresh(realm.handle.pointer, false); - } - SchedulerHandle createScheduler(int isolateId, int sendPort) { final schedulerPtr = realmLib.realm_dart_create_scheduler(isolateId, sendPort); return SchedulerHandle._(schedulerPtr); @@ -403,131 +395,6 @@ class _RealmCore { return realmLib.realm_get_library_cpu_arch().cast().toDartString(); } - void closeRealm(Realm realm) { - invokeGetBool(() => realmLib.realm_close(realm.handle.pointer), "Realm close failed"); - } - - bool isRealmClosed(Realm realm) { - return realmLib.realm_is_closed(realm.handle.pointer); - } - - void beginWrite(Realm realm) { - invokeGetBool(() => realmLib.realm_begin_write(realm.handle.pointer), "Could not begin write"); - } - - void commitWrite(Realm realm) { - invokeGetBool(() => realmLib.realm_commit(realm.handle.pointer), "Could not commit write"); - } - - Future beginWriteAsync(Realm realm, CancellationToken? ct) { - int? id; - final completer = CancellableCompleter(ct, onCancel: () { - if (id != null) { - realmCore._cancelAsync(realm, id!); - } - }); - if (ct?.isCancelled != true) { - using((arena) { - final transaction_id = arena(); - invokeGetBool(() => realmLib.realm_async_begin_write( - realm.handle.pointer, - Pointer.fromFunction(_completeAsyncBeginWrite), - completer.toPersistentHandle(), - realmLib.addresses.realm_dart_delete_persistent_handle, - true, - transaction_id, - )); - id = transaction_id.value; - }); - } - return completer.future; - } - - Future commitWriteAsync(Realm realm, CancellationToken? ct) { - int? id; - final completer = CancellableCompleter(ct, onCancel: () { - if (id != null) { - realmCore._cancelAsync(realm, id!); - } - }); - if (ct?.isCancelled != true) { - using((arena) { - final transaction_id = arena(); - invokeGetBool(() => realmLib.realm_async_commit( - realm.handle.pointer, - Pointer.fromFunction(_completeAsyncCommit), - completer.toPersistentHandle(), - realmLib.addresses.realm_dart_delete_persistent_handle, - false, - transaction_id, - )); - id = transaction_id.value; - }); - } - return completer.future; - } - - bool _cancelAsync(Realm realm, int cancellationId) { - return using((Arena arena) { - final didCancel = arena(); - invokeGetBool(() => realmLib.realm_async_cancel(realm.handle.pointer, cancellationId, didCancel)); - return didCancel.value; - }); - } - - static void _completeAsyncBeginWrite(Pointer userdata) { - final Completer completer = userdata.toObject(); - completer.complete(); - } - - static void _completeAsyncCommit(Pointer userdata, bool error, Pointer description) { - final Completer completer = userdata.toObject(); - if (error) { - completer.completeError(RealmException(description.cast().toDartString())); - } else { - completer.complete(); - } - } - - bool getIsWritable(Realm realm) { - return realmLib.realm_is_writable(realm.handle.pointer); - } - - void rollbackWrite(Realm realm) { - invokeGetBool(() => realmLib.realm_rollback(realm.handle.pointer), "Could not rollback write"); - } - - bool realmRefresh(Realm realm) { - return using((Arena arena) { - final did_refresh = arena(); - invokeGetBool(() => realmLib.realm_refresh(realm.handle.pointer, did_refresh), "Could not refresh"); - return did_refresh.value; - }); - } - - Future realmRefreshAsync(Realm realm) async { - final completer = Completer(); - final callback = Pointer.fromFunction)>(_realmRefreshAsyncCallback); - Pointer completerPtr = realmLib.realm_dart_object_to_persistent_handle(completer); - Pointer result = - realmLib.realm_add_realm_refresh_callback(realm.handle.pointer, callback.cast(), completerPtr, realmLib.addresses.realm_dart_delete_persistent_handle); - - if (result == nullptr) { - return Future.value(false); - } - - return completer.future; - } - - static void _realmRefreshAsyncCallback(Pointer userdata) { - if (userdata == nullptr) { - return; - } - - final completer = realmLib.realm_dart_persistent_handle_to_object(userdata) as Completer; - completer.complete(true); - } - RealmObjectMetadata getObjectMetadata(Realm realm, SchemaObject schema) { return using((Arena arena) { final found = arena(); @@ -1999,10 +1866,6 @@ class _RealmCore { return token.cast().toRealmDartString(freeRealmMemory: true)!; } - SessionHandle realmGetSession(Realm realm) { - return SessionHandle._(invokeGetPointer(() => realmLib.realm_sync_session_get(realm.handle.pointer)), realm.handle); - } - String sessionGetPath(Session session) { return realmLib.realm_sync_session_get_file_path(session.handle.pointer).cast().toRealmDartString()!; } @@ -2205,12 +2068,8 @@ class _RealmCore { return completer.future; } - bool isFrozen(Realm realm) { - return realmLib.realm_is_frozen(realm.handle.pointer.cast()); - } - ResultsHandle resolveResults(RealmResults realmResults, Realm frozenRealm) => realmResults.handle.resolveIn(frozenRealm.handle); - + ObjectHandle? resolveObject(RealmObjectBase object, Realm frozenRealm) { return using((Arena arena) { final resultPtr = arena>(); @@ -2466,8 +2325,6 @@ class _RealmCore { }); } - bool compact(Realm realm) => realm.handle.compact(); - bool immediatelyRunFileActions(App app, String realmPath) { return using((arena) { final out_did_run = arena(); @@ -2477,8 +2334,6 @@ class _RealmCore { }); } - void writeCopy(Realm realm, Configuration config) => realm.handle.writeCopy(config); - void _createCollection(Realm realm, RealmValue value, Pointer Function() createList, Pointer Function() createMap) { CollectionHandleBase? collectionHandle; try { diff --git a/packages/realm_dart/lib/src/native/realm_handle.dart b/packages/realm_dart/lib/src/native/realm_handle.dart index 1a8039e0d..ba92a80ad 100644 --- a/packages/realm_dart/lib/src/native/realm_handle.dart +++ b/packages/realm_dart/lib/src/native/realm_handle.dart @@ -99,4 +99,145 @@ class RealmHandle extends HandleBase { } RealmHandle freeze() => RealmHandle._(invokeGetPointer(() => realmLib.realm_freeze(pointer))); + + SessionHandle getSession() { + return SessionHandle._(invokeGetPointer(() => realmLib.realm_sync_session_get(pointer)), this); + } + + bool get isFrozen { + return realmLib.realm_is_frozen(pointer.cast()); + } + + SubscriptionSetHandle get subscriptions { + return SubscriptionSetHandle._(invokeGetPointer(() => realmLib.realm_sync_get_active_subscription_set(pointer)), this); + } + + void disableAutoRefreshForTesting() { + realmLib.realm_set_auto_refresh(pointer, false); + } + + void close() { + invokeGetBool(() => realmLib.realm_close(pointer), "Realm close failed"); + } + + bool get isClosed { + return realmLib.realm_is_closed(pointer); + } + + void beginWrite() { + invokeGetBool(() => realmLib.realm_begin_write(pointer), "Could not begin write"); + } + + void commitWrite() { + invokeGetBool(() => realmLib.realm_commit(pointer), "Could not commit write"); + } + + Future beginWriteAsync(CancellationToken? ct) { + int? id; + final completer = CancellableCompleter(ct, onCancel: () { + if (id != null) { + _cancelAsync(id!); + } + }); + if (ct?.isCancelled != true) { + using((arena) { + final transactionId = arena(); + invokeGetBool(() => realmLib.realm_async_begin_write( + pointer, + Pointer.fromFunction(_completeAsyncBeginWrite), + completer.toPersistentHandle(), + realmLib.addresses.realm_dart_delete_persistent_handle, + true, + transactionId, + )); + id = transactionId.value; + }); + } + return completer.future; + } + + Future commitWriteAsync(CancellationToken? ct) { + int? id; + final completer = CancellableCompleter(ct, onCancel: () { + if (id != null) { + _cancelAsync(id!); + } + }); + if (ct?.isCancelled != true) { + using((arena) { + final transactionId = arena(); + invokeGetBool(() => realmLib.realm_async_commit( + pointer, + Pointer.fromFunction(_completeAsyncCommit), + completer.toPersistentHandle(), + realmLib.addresses.realm_dart_delete_persistent_handle, + false, + transactionId, + )); + id = transactionId.value; + }); + } + return completer.future; + } + + bool _cancelAsync(int cancellationId) { + return using((Arena arena) { + final didCancel = arena(); + invokeGetBool(() => realmLib.realm_async_cancel(pointer, cancellationId, didCancel)); + return didCancel.value; + }); + } + + static void _completeAsyncBeginWrite(Pointer userdata) { + final Completer completer = userdata.toObject(); + completer.complete(); + } + + static void _completeAsyncCommit(Pointer userdata, bool error, Pointer description) { + final Completer completer = userdata.toObject(); + if (error) { + completer.completeError(RealmException(description.cast().toDartString())); + } else { + completer.complete(); + } + } + + bool get isWritable { + return realmLib.realm_is_writable(pointer); + } + + void rollbackWrite() { + invokeGetBool(() => realmLib.realm_rollback(pointer), "Could not rollback write"); + } + + bool refresh() { + return using((Arena arena) { + final didRefresh = arena(); + invokeGetBool(() => realmLib.realm_refresh(pointer, didRefresh), "Could not refresh"); + return didRefresh.value; + }); + } + + Future refreshAsync() async { + final completer = Completer(); + final callback = Pointer.fromFunction)>(_realmRefreshAsyncCallback); + Pointer completerPtr = realmLib.realm_dart_object_to_persistent_handle(completer); + Pointer result = + realmLib.realm_add_realm_refresh_callback(pointer, callback.cast(), completerPtr, realmLib.addresses.realm_dart_delete_persistent_handle); + + if (result == nullptr) { + return Future.value(false); + } + + return completer.future; + } + + static void _realmRefreshAsyncCallback(Pointer userdata) { + if (userdata == nullptr) { + return; + } + + final completer = realmLib.realm_dart_persistent_handle_to_object(userdata) as Completer; + completer.complete(true); + } } diff --git a/packages/realm_dart/lib/src/realm_class.dart b/packages/realm_dart/lib/src/realm_class.dart index bdc3cd4a4..ef167b176 100644 --- a/packages/realm_dart/lib/src/realm_class.dart +++ b/packages/realm_dart/lib/src/realm_class.dart @@ -127,7 +127,7 @@ class Realm implements Finalizable { /// Gets a value indicating whether this [Realm] is frozen. Frozen Realms are immutable /// and will not update when writes are made to the database. - late final bool isFrozen = realmCore.isFrozen(this); + late final bool isFrozen = this.handle.isFrozen; /// Opens a `Realm` using a [Configuration] object. Realm(Configuration config) : this._(config); @@ -345,7 +345,7 @@ class Realm implements Finalizable { } /// Checks whether the `Realm` is in write transaction. - bool get isInTransaction => realmCore.getIsWritable(this); + bool get isInTransaction => this.handle.isWritable; /// Synchronously calls the provided callback inside a write transaction. /// @@ -366,14 +366,14 @@ class Realm implements Finalizable { /// Begins a write transaction for this [Realm]. Transaction beginWrite() { - realmCore.beginWrite(this); + this.handle.beginWrite(); return Transaction._(this); } /// Asynchronously begins a write transaction for this [Realm]. You can supply a /// [CancellationToken] to cancel the operation. Future beginWriteAsync([CancellationToken? cancellationToken]) async { - await realmCore.beginWriteAsync(this, cancellationToken); + await this.handle.beginWriteAsync(cancellationToken); return Transaction._(this); } @@ -404,12 +404,12 @@ class Realm implements Finalizable { } _schemaCallbackHandle?.release(); - realmCore.closeRealm(this); + this.handle.close(); handle.release(); } /// Checks whether the `Realm` is closed. - bool get isClosed => _handle.released || realmCore.isRealmClosed(this); + bool get isClosed => _handle.released || this.handle.isClosed; /// Fast lookup for a [RealmObject] with the specified [primaryKey]. T? find(Object? primaryKey) { @@ -480,7 +480,7 @@ class Realm implements Finalizable { var result = _subscriptions?.target; if (result == null || result.handle.released) { - result = SubscriptionSetInternal.create(this, realmCore.getSubscriptions(this)); + result = SubscriptionSetInternal.create(this, this.handle.subscriptions); result.handle.refresh(); _subscriptions = WeakReference(result); } @@ -500,7 +500,7 @@ class Realm implements Finalizable { var result = _syncSession?.target; if (result == null || result.handle.released) { - result = SessionInternal.create(realmCore.realmGetSession(this)); + result = SessionInternal.create(this.handle.getSession()); _syncSession = WeakReference(result); } @@ -563,7 +563,7 @@ class Realm implements Finalizable { realm.syncSession.pause(); } try { - return realmCore.compact(realm); + return realm.handle.compact(); } finally { realm.close(); } @@ -583,7 +583,7 @@ class Realm implements Finalizable { throw RealmError("Copying a Realm is not allowed within a write transaction or during migration."); } - realmCore.writeCopy(this, config); + this.handle.writeCopy(config); } /// Update the `Realm` instance and outstanding objects to point to the most recent persisted version. @@ -593,7 +593,7 @@ class Realm implements Finalizable { /// Typically you don't need to call this method since Realm has auto-refresh built-in. /// Note that this may return `true` even if no data has actually changed. bool refresh() { - return realmCore.realmRefresh(this); + return this.handle.refresh(); } /// Returns a [Future] that will complete when the `Realm` is refreshed to the version which is the @@ -601,7 +601,7 @@ class Realm implements Finalizable { /// /// Note that this may return `true` even if no data has actually changed. Future refreshAsync() async { - return realmCore.realmRefreshAsync(this); + return this.handle.refreshAsync(); } /// Allows listening for schema changes on this Realm. Only dynamic and synchronized @@ -645,6 +645,8 @@ class Realm implements Finalizable { } } } + + void disableAutoRefreshForTesting() => handle.disableAutoRefreshForTesting(); } /// Describes the schema changes that occurred on a Realm @@ -674,7 +676,7 @@ class Transaction { void commit() { final realm = _ensureOpen('commit'); - realmCore.commitWrite(realm); + realm.handle.commitWrite(); _closeTransaction(); } @@ -685,7 +687,7 @@ class Transaction { Future commitAsync([CancellationToken? cancellationToken]) async { final realm = _ensureOpen('commitAsync'); - await realmCore.commitWriteAsync(realm, cancellationToken); + await realm.handle.commitWriteAsync(cancellationToken); _closeTransaction(); } @@ -695,7 +697,7 @@ class Transaction { final realm = _ensureOpen('rollback'); if (!realm.isClosed) { - realmCore.rollbackWrite(realm); + realm.handle.rollbackWrite(); } _closeTransaction(); diff --git a/packages/realm_dart/test/realm_test.dart b/packages/realm_dart/test/realm_test.dart index 6625290ba..cedd5548e 100644 --- a/packages/realm_dart/test/realm_test.dart +++ b/packages/realm_dart/test/realm_test.dart @@ -1819,7 +1819,7 @@ void main() { final results = realm.query(r"name == $0", [personName]); expect(realm.refresh(), false); - realmCore.realmDisableAutoRefreshForTesting(realm); + realm.handle.disableAutoRefreshForTesting(); ReceivePort receivePort = ReceivePort(); Isolate.spawn((SendPort sendPort) async { From 79ecfc59914b3f9045a5898d56c416e7254f26cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Sat, 13 Apr 2024 14:31:19 +0200 Subject: [PATCH 20/68] Don't need Tuple --- packages/realm_common/lib/src/realm_common_base.dart | 10 +--------- packages/realm_dart/lib/src/native/realm_core.dart | 4 ++-- packages/realm_dart/lib/src/realm_object.dart | 6 +++--- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/packages/realm_common/lib/src/realm_common_base.dart b/packages/realm_common/lib/src/realm_common_base.dart index e89b97b27..aecd823a4 100644 --- a/packages/realm_common/lib/src/realm_common_base.dart +++ b/packages/realm_common/lib/src/realm_common_base.dart @@ -129,12 +129,4 @@ class Backlink { /// The name of the field in the other class that links to this class. final Symbol fieldName; const Backlink(this.fieldName); -} - -/// @nodoc -class Tuple { - T1 item1; - T2 item2; - - Tuple(this.item1, this.item2); -} +} \ No newline at end of file diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index f8ad5dc3f..523a53530 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -442,7 +442,7 @@ class _RealmCore { return result; } - Tuple getEmbeddedParent(EmbeddedObject obj) { + (ObjectHandle, int) getEmbeddedParent(EmbeddedObject obj) { return using((Arena arena) { final parentPtr = arena>(); final classKeyPtr = arena(); @@ -450,7 +450,7 @@ class _RealmCore { final handle = ObjectHandle._(parentPtr.value, obj.realm.handle); - return Tuple(handle, classKeyPtr.value); + return (handle, classKeyPtr.value); }); } diff --git a/packages/realm_dart/lib/src/realm_object.dart b/packages/realm_dart/lib/src/realm_object.dart index d03217aa7..f9ccc0921 100644 --- a/packages/realm_dart/lib/src/realm_object.dart +++ b/packages/realm_dart/lib/src/realm_object.dart @@ -636,9 +636,9 @@ extension EmbeddedObjectExtension on EmbeddedObject { return null; } - final parent = realmCore.getEmbeddedParent(this); - final (type, metadata) = realm.metadata.getByClassKey(parent.item2); - return realm.createObject(type, parent.item1, metadata); + final (handle, classKey) = realmCore.getEmbeddedParent(this); + final (type, metadata) = realm.metadata.getByClassKey(classKey); + return realm.createObject(type, handle, metadata); } } From 3a967dac7c58959720d196af1f44794ca17833f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Sat, 13 Apr 2024 14:39:16 +0200 Subject: [PATCH 21/68] Expose disableAutoRefreshForTesting --- packages/realm_dart/test/realm_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/realm_dart/test/realm_test.dart b/packages/realm_dart/test/realm_test.dart index cedd5548e..398f2d221 100644 --- a/packages/realm_dart/test/realm_test.dart +++ b/packages/realm_dart/test/realm_test.dart @@ -1819,7 +1819,7 @@ void main() { final results = realm.query(r"name == $0", [personName]); expect(realm.refresh(), false); - realm.handle.disableAutoRefreshForTesting(); + realm.disableAutoRefreshForTesting(); ReceivePort receivePort = ReceivePort(); Isolate.spawn((SendPort sendPort) async { From 89550b40b66b29d89f6e30f9b43352947474403a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Sat, 13 Apr 2024 15:07:42 +0200 Subject: [PATCH 22/68] Refactor UserHandle --- .../realm_dart/lib/src/configuration.dart | 2 +- .../realm_dart/lib/src/native/realm_core.dart | 94 +------------------ .../lib/src/native/user_handle.dart | 93 ++++++++++++++++++ packages/realm_dart/lib/src/user.dart | 20 ++-- 4 files changed, 105 insertions(+), 104 deletions(-) create mode 100644 packages/realm_dart/lib/src/native/user_handle.dart diff --git a/packages/realm_dart/lib/src/configuration.dart b/packages/realm_dart/lib/src/configuration.dart index f9a5e713a..5084bbac6 100644 --- a/packages/realm_dart/lib/src/configuration.dart +++ b/packages/realm_dart/lib/src/configuration.dart @@ -368,7 +368,7 @@ class FlexibleSyncConfiguration extends Configuration { }) : super._(); @override - String get _defaultPath => realmCore.getPathForUser(user); + String get _defaultPath => user.handle.path; } extension FlexibleSyncConfigurationInternal on FlexibleSyncConfiguration { diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 523a53530..6de9bf05f 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -54,6 +54,7 @@ part 'rooted_handle.dart'; part 'schema_handle.dart'; part 'subscription_handle.dart'; part 'subscription_set_handle.dart'; +part 'user_handle.dart'; final _pluginLib = () { if (!isFlutterPlatform) { @@ -207,16 +208,6 @@ class _RealmCore { // realmLib.realm_dart_gc(); // } - String getPathForUser(User user) { - final syncConfigPtr = invokeGetPointer(() => realmLib.realm_flx_sync_config_new(user.handle.pointer)); - try { - final path = realmLib.realm_app_sync_client_get_default_file_path_for_realm(syncConfigPtr, nullptr); - return path.cast().toRealmDartString(freeRealmMemory: true)!; - } finally { - realmLib.realm_release(syncConfigPtr.cast()); - } - } - void raiseError(Session session, int errorCode, bool isFatal) { using((arena) { final message = "Simulated session error".toCharPtr(arena); @@ -1753,11 +1744,6 @@ class _RealmCore { return completer.future; } - String? userGetCustomData(User user) { - final customDataPtr = realmLib.realm_user_get_custom_data(user.handle.pointer); - return customDataPtr.cast().toRealmDartString(freeRealmMemory: true, treatEmptyAsNull: true); - } - Future userRefreshCustomData(App app, User user) { final completer = Completer(); invokeGetBool( @@ -1787,85 +1773,11 @@ class _RealmCore { return completer.future; } - UserState userGetState(User user) { - final nativeUserState = realmLib.realm_user_get_state(user.handle.pointer); - return UserState.values.fromIndex(nativeUserState); - } - - String userGetId(User user) { - final idPtr = invokeGetPointer(() => realmLib.realm_user_get_identity(user.handle.pointer), "Error while getting user id"); - final userId = idPtr.cast().toDartString(); - return userId; - } - - AppHandle userGetApp(UserHandle userHandle) { - final appPtr = realmLib.realm_user_get_app(userHandle.pointer); - if (appPtr == nullptr) { - throw RealmException('User does not have an associated app. This is likely due to the user being logged out.'); - } - - return AppHandle._(appPtr); - } - - List userGetIdentities(User user) { - return using((arena) { - return _userGetIdentities(user, arena); - }); - } - - List _userGetIdentities(User user, Arena arena, {int expectedSize = 2}) { - final actualCount = arena(); - final identitiesPtr = arena(expectedSize); - invokeGetBool(() => realmLib.realm_user_get_all_identities(user.handle.pointer, identitiesPtr, expectedSize, actualCount)); - - if (expectedSize < actualCount.value) { - // The supplied array was too small - resize it - arena.free(identitiesPtr); - return _userGetIdentities(user, arena, expectedSize: actualCount.value); - } - - final result = []; - for (var i = 0; i < actualCount.value; i++) { - final identity = identitiesPtr.elementAt(i).ref; - - result.add(UserIdentityInternal.create( - identity.id.cast().toRealmDartString(freeRealmMemory: true)!, AuthProviderTypeInternal.getByValue(identity.provider_type))); - } - - return result; - } - - Future userLogOut(User user) { - invokeGetBool(() => realmLib.realm_user_log_out(user.handle.pointer), "Logout failed"); - return Future.value(); - } - - String? userGetDeviceId(User user) { - final deviceId = invokeGetPointer(() => realmLib.realm_user_get_device_id(user.handle.pointer)); - return deviceId.cast().toRealmDartString(treatEmptyAsNull: true, freeRealmMemory: true); - } - AuthProviderType userGetCredentialsProviderType(Credentials credentials) { final provider = realmLib.realm_auth_credentials_get_provider(credentials.handle.pointer); return AuthProviderTypeInternal.getByValue(provider); } - UserProfile userGetProfileData(User user) { - final data = invokeGetPointer(() => realmLib.realm_user_get_profile_data(user.handle.pointer)); - final dynamic profileData = jsonDecode(data.cast().toRealmDartString(freeRealmMemory: true)!); - return UserProfile(profileData as Map); - } - - String userGetRefreshToken(User user) { - final token = invokeGetPointer(() => realmLib.realm_user_get_refresh_token(user.handle.pointer)); - return token.cast().toRealmDartString(freeRealmMemory: true)!; - } - - String userGetAccessToken(User user) { - final token = invokeGetPointer(() => realmLib.realm_user_get_access_token(user.handle.pointer)); - return token.cast().toRealmDartString(freeRealmMemory: true)!; - } - String sessionGetPath(Session session) { return realmLib.realm_sync_session_get_file_path(session.handle.pointer).cast().toRealmDartString()!; } @@ -2460,10 +2372,6 @@ class AppHandle extends HandleBase { AppHandle._(Pointer pointer) : super(pointer, 16); } -class UserHandle extends HandleBase { - UserHandle._(Pointer pointer) : super(pointer, 24); -} - class RealmAsyncOpenTaskHandle extends HandleBase { RealmAsyncOpenTaskHandle._(Pointer pointer) : super(pointer, 32); } diff --git a/packages/realm_dart/lib/src/native/user_handle.dart b/packages/realm_dart/lib/src/native/user_handle.dart new file mode 100644 index 000000000..bb0993b23 --- /dev/null +++ b/packages/realm_dart/lib/src/native/user_handle.dart @@ -0,0 +1,93 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + +part of 'realm_core.dart'; + +class UserHandle extends HandleBase { + UserHandle._(Pointer pointer) : super(pointer, 24); + + AppHandle get app { + return realmLib.realm_user_get_app(pointer).convert(AppHandle._) ?? + (throw RealmException('User does not have an associated app. This is likely due to the user being logged out.')); + } + + UserState get state { + final nativeUserState = realmLib.realm_user_get_state(pointer); + return UserState.values.fromIndex(nativeUserState); + } + + String get id { + final idPtr = invokeGetPointer(() => realmLib.realm_user_get_identity(pointer), "Error while getting user id"); + final userId = idPtr.cast().toDartString(); + return userId; + } + + List get identities { + return using((arena) { + return _userGetIdentities(arena); + }); + } + + List _userGetIdentities(Arena arena, {int expectedSize = 2}) { + final actualCount = arena(); + final identitiesPtr = arena(expectedSize); + invokeGetBool(() => realmLib.realm_user_get_all_identities(pointer, identitiesPtr, expectedSize, actualCount)); + + if (expectedSize < actualCount.value) { + // The supplied array was too small - resize it + arena.free(identitiesPtr); + return _userGetIdentities(arena, expectedSize: actualCount.value); + } + + final result = []; + for (var i = 0; i < actualCount.value; i++) { + final identity = identitiesPtr.elementAt(i).ref; + + result.add(UserIdentityInternal.create( + identity.id.cast().toRealmDartString(freeRealmMemory: true)!, AuthProviderTypeInternal.getByValue(identity.provider_type))); + } + + return result; + } + + Future logOut() { + invokeGetBool(() => realmLib.realm_user_log_out(pointer), "Logout failed"); + return Future.value(); // why?! + } + + String? get deviceId { + final deviceId = invokeGetPointer(() => realmLib.realm_user_get_device_id(pointer)); + return deviceId.cast().toRealmDartString(treatEmptyAsNull: true, freeRealmMemory: true); + } + + UserProfile get profileData { + final data = invokeGetPointer(() => realmLib.realm_user_get_profile_data(pointer)); + final dynamic profileData = jsonDecode(data.cast().toRealmDartString(freeRealmMemory: true)!); + return UserProfile(profileData as Map); + } + + String get refreshToken { + final token = invokeGetPointer(() => realmLib.realm_user_get_refresh_token(pointer)); + return token.cast().toRealmDartString(freeRealmMemory: true)!; + } + + String get accessToken { + final token = invokeGetPointer(() => realmLib.realm_user_get_access_token(pointer)); + return token.cast().toRealmDartString(freeRealmMemory: true)!; + } + + String get path { + final syncConfigPtr = invokeGetPointer(() => realmLib.realm_flx_sync_config_new(pointer)); + try { + final path = realmLib.realm_app_sync_client_get_default_file_path_for_realm(syncConfigPtr, nullptr); + return path.cast().toRealmDartString(freeRealmMemory: true)!; + } finally { + realmLib.realm_release(syncConfigPtr.cast()); + } + } + + String? get customData { + final customDataPtr = realmLib.realm_user_get_custom_data(pointer); + return customDataPtr.cast().toRealmDartString(freeRealmMemory: true, treatEmptyAsNull: true); + } +} diff --git a/packages/realm_dart/lib/src/user.dart b/packages/realm_dart/lib/src/user.dart index b1a43c2c1..765bf5054 100644 --- a/packages/realm_dart/lib/src/user.dart +++ b/packages/realm_dart/lib/src/user.dart @@ -33,7 +33,7 @@ class User { App get app { // The _app field may be null when we're retrieving a user from the session // rather than from the app. - return _app ??= AppInternal.create(realmCore.userGetApp(_handle)); + return _app ??= AppInternal.create(_handle.app); } late final ApiKeyClient _apiKeys = ApiKeyClient._(this); @@ -61,49 +61,49 @@ class User { /// The current state of this [User]. UserState get state { - return realmCore.userGetState(this); + return this.handle.state; } /// Get this [User]'s id on MongoDB Atlas. String get id { - return realmCore.userGetId(this); + return this.handle.id; } /// Gets a collection of all identities associated with this [User]. List get identities { - return realmCore.userGetIdentities(this); + return this.handle.identities; } /// Removes the [User]'s local credentials. This will also close any associated Sessions. Future logOut() async { - return await realmCore.userLogOut(this); + return await this.handle.logOut(); } /// Gets an unique identifier for the current device. String? get deviceId { - return realmCore.userGetDeviceId(this); + return this.handle.deviceId; } /// Gets the profile information for this [User]. UserProfile get profile { - return realmCore.userGetProfileData(this); + return this.handle.profileData; } /// Gets the refresh token for this [User]. This is the user's credential for /// accessing [Atlas App Services](https://www.mongodb.com/docs/atlas/app-services/) and should be treated as sensitive data. String get refreshToken { - return realmCore.userGetRefreshToken(this); + return this.handle.refreshToken; } /// Gets the access token for this [User]. This is the user's credential for /// accessing [Atlas App Services](https://www.mongodb.com/docs/atlas/app-services/) and should be treated as sensitive data. String get accessToken { - return realmCore.userGetAccessToken(this); + return this.handle.accessToken; } /// The custom user data associated with this [User]. dynamic get customData { - final data = realmCore.userGetCustomData(this); + final data = this.handle.customData; if (data == null) { return null; } From e867005d27fd20acaafec57c2b38316781aa7242 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Sat, 13 Apr 2024 15:11:46 +0200 Subject: [PATCH 23/68] RealmHandle.findAll --- packages/realm_dart/lib/src/native/realm_core.dart | 5 ----- packages/realm_dart/lib/src/native/realm_handle.dart | 5 +++++ packages/realm_dart/lib/src/realm_class.dart | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 6de9bf05f..535b8206c 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -516,11 +516,6 @@ class _RealmCore { invokeGetBool(() => realmLib.realm_object_delete(object.handle.pointer)); } - ResultsHandle findAll(Realm realm, int classKey) { - final pointer = invokeGetPointer(() => realmLib.realm_object_find_all(realm.handle.pointer, classKey)); - return ResultsHandle._(pointer, realm.handle); - } - ResultsHandle queryList(RealmList target, String query, List args) { return using((arena) { final length = args.length; diff --git a/packages/realm_dart/lib/src/native/realm_handle.dart b/packages/realm_dart/lib/src/native/realm_handle.dart index ba92a80ad..5dc67dc41 100644 --- a/packages/realm_dart/lib/src/native/realm_handle.dart +++ b/packages/realm_dart/lib/src/native/realm_handle.dart @@ -240,4 +240,9 @@ class RealmHandle extends HandleBase { final completer = realmLib.realm_dart_persistent_handle_to_object(userdata) as Completer; completer.complete(true); } + + ResultsHandle findAll(int classKey) { + final ptr = invokeGetPointer(() => realmLib.realm_object_find_all(pointer, classKey)); + return ResultsHandle._(ptr, this); + } } diff --git a/packages/realm_dart/lib/src/realm_class.dart b/packages/realm_dart/lib/src/realm_class.dart index ef167b176..5cd38dd58 100644 --- a/packages/realm_dart/lib/src/realm_class.dart +++ b/packages/realm_dart/lib/src/realm_class.dart @@ -430,7 +430,7 @@ class Realm implements Finalizable { /// The returned [RealmResults] allows iterating all the values without further filtering. RealmResults all() { final metadata = _metadata.getByType(T); - final handle = realmCore.findAll(this, metadata.classKey); + final handle = this.handle.findAll(metadata.classKey); return RealmResultsInternal.create(handle, this, metadata); } @@ -780,7 +780,7 @@ extension RealmInternal on Realm { /// This should only be used for testing RealmResults allEmbedded() { final metadata = _metadata.getByType(T); - final handle = realmCore.findAll(this, metadata.classKey); + final handle = this.handle.findAll(metadata.classKey); return RealmResultsInternal.create(handle, this, metadata); } @@ -955,7 +955,7 @@ class DynamicRealm { /// The returned [RealmResults] allows iterating all the values without further filtering. RealmResults all(String className) { final metadata = _realm._metadata.getByName(className); - final handle = realmCore.findAll(_realm, metadata.classKey); + final handle = _realm.handle.findAll(metadata.classKey); return RealmResultsInternal.create(handle, _realm, metadata); } From 77338d0dafdef2e3f28ae93c628b9bbc1c294d49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Sat, 13 Apr 2024 15:24:06 +0200 Subject: [PATCH 24/68] Realm.find/.findExiting/.renameProperty --- packages/realm_dart/lib/src/migration.dart | 6 +-- .../realm_dart/lib/src/native/realm_core.dart | 38 ------------------- .../lib/src/native/realm_handle.dart | 32 ++++++++++++++++ packages/realm_dart/lib/src/realm_class.dart | 34 ++++++++--------- 4 files changed, 52 insertions(+), 58 deletions(-) diff --git a/packages/realm_dart/lib/src/migration.dart b/packages/realm_dart/lib/src/migration.dart index 7c02226a1..3b6823cb6 100644 --- a/packages/realm_dart/lib/src/migration.dart +++ b/packages/realm_dart/lib/src/migration.dart @@ -33,7 +33,7 @@ class Migration { } final metadata = newRealm.metadata.getByType(T); - final handle = realmCore.findExisting(newRealm, metadata.classKey, oldObject.handle); + final handle = newRealm.handle.findExisting(metadata.classKey, oldObject.handle); if (handle == null) { return null; } @@ -45,7 +45,7 @@ class Migration { /// Renames a property during a migration. void renameProperty(String className, String oldPropertyName, String newPropertyName) { - realmCore.renameProperty(newRealm, className, oldPropertyName, newPropertyName, _schema); + newRealm.handle.renameProperty(className, oldPropertyName, newPropertyName, _schema); } /// Deletes a type during a migration. All the data associated with the type, as well as its schema, @@ -55,7 +55,7 @@ class Migration { /// /// Returns `true` if the table was present in the old Realm and was deleted. Returns `false` if it didn't exist. bool deleteType(String className) { - return realmCore.deleteType(newRealm, className); + return newRealm.handle.deleteType(className); } } diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 535b8206c..729c2e2a6 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -445,11 +445,6 @@ class _RealmCore { }); } - ObjectHandle getOrCreateRealmObjectWithPrimaryKey(Realm realm, int classKey, Object? primaryKey) => - realm.handle.getOrCreateWithPrimaryKey(classKey, primaryKey); - - ObjectHandle createRealmObjectWithPrimaryKey(Realm realm, int classKey, Object? primaryKey) => realm.handle.createWithPrimaryKey(classKey, primaryKey); - Object? getProperty(RealmObjectBase object, int propertyKey) { return using((Arena arena) { final realm_value = arena(); @@ -479,39 +474,6 @@ class _RealmCore { // ignore: unused_element int get _threadId => realmLib.realm_dart_get_thread_id(); - ObjectHandle? find(Realm realm, int classKey, Object? primaryKey) { - return using((Arena arena) { - final realm_value = _toRealmValue(primaryKey, arena); - final pointer = realmLib.realm_object_find_with_primary_key(realm.handle.pointer, classKey, realm_value.ref, nullptr); - if (pointer == nullptr) { - return null; - } - - return ObjectHandle._(pointer, realm.handle); - }); - } - - ObjectHandle? findExisting(Realm realm, int classKey, ObjectHandle other) { - final key = realmLib.realm_object_get_key(other.pointer); - final pointer = invokeGetPointer(() => realmLib.realm_get_object(realm.handle.pointer, classKey, key)); - return ObjectHandle._(pointer, realm.handle); - } - - void renameProperty(Realm realm, String objectType, String oldName, String newName, SchemaHandle schema) { - using((Arena arena) { - invokeGetBool(() => realmLib.realm_schema_rename_property( - realm.handle.pointer, schema.pointer, objectType.toCharPtr(arena), oldName.toCharPtr(arena), newName.toCharPtr(arena))); - }); - } - - bool deleteType(Realm realm, String objectType) { - return using((Arena arena) { - final deletedPtr = arena(); - invokeGetBool(() => realmLib.realm_remove_table(realm.handle.pointer, objectType.toCharPtr(arena), deletedPtr)); - return deletedPtr.value; - }); - } - void deleteRealmObject(RealmObjectBase object) { invokeGetBool(() => realmLib.realm_object_delete(object.handle.pointer)); } diff --git a/packages/realm_dart/lib/src/native/realm_handle.dart b/packages/realm_dart/lib/src/native/realm_handle.dart index 5dc67dc41..b34403c93 100644 --- a/packages/realm_dart/lib/src/native/realm_handle.dart +++ b/packages/realm_dart/lib/src/native/realm_handle.dart @@ -245,4 +245,36 @@ class RealmHandle extends HandleBase { final ptr = invokeGetPointer(() => realmLib.realm_object_find_all(pointer, classKey)); return ResultsHandle._(ptr, this); } + + ObjectHandle? find(int classKey, Object? primaryKey) { + return using((Arena arena) { + final realmValue = _toRealmValue(primaryKey, arena); + final ptr = realmLib.realm_object_find_with_primary_key(pointer, classKey, realmValue.ref, nullptr); + if (ptr == nullptr) { + return null; + } + return ObjectHandle._(ptr, this); + }); + } + + ObjectHandle? findExisting(int classKey, ObjectHandle other) { + final key = realmLib.realm_object_get_key(other.pointer); + final ptr = invokeGetPointer(() => realmLib.realm_get_object(pointer, classKey, key)); + return ptr.convert((p) => ObjectHandle._(p, this)); + } + + void renameProperty(String objectType, String oldName, String newName, SchemaHandle schema) { + using((Arena arena) { + invokeGetBool(() => + realmLib.realm_schema_rename_property(pointer, schema.pointer, objectType.toCharPtr(arena), oldName.toCharPtr(arena), newName.toCharPtr(arena))); + }); + } + + bool deleteType(String objectType) { + return using((Arena arena) { + final tableDeleted = arena(); + invokeGetBool(() => realmLib.realm_remove_table(pointer, objectType.toCharPtr(arena), tableDeleted)); + return tableDeleted.value; + }); + } } diff --git a/packages/realm_dart/lib/src/realm_class.dart b/packages/realm_dart/lib/src/realm_class.dart index 5cd38dd58..c13226178 100644 --- a/packages/realm_dart/lib/src/realm_class.dart +++ b/packages/realm_dart/lib/src/realm_class.dart @@ -127,7 +127,7 @@ class Realm implements Finalizable { /// Gets a value indicating whether this [Realm] is frozen. Frozen Realms are immutable /// and will not update when writes are made to the database. - late final bool isFrozen = this.handle.isFrozen; + late final bool isFrozen = handle.isFrozen; /// Opens a `Realm` using a [Configuration] object. Realm(Configuration config) : this._(config); @@ -287,12 +287,12 @@ class Realm implements Finalizable { final key = metadata.classKey; final primaryKey = metadata.primaryKey; if (primaryKey == null) { - return this.handle.create(key); + return handle.create(key); } if (update) { - return realmCore.getOrCreateRealmObjectWithPrimaryKey(this, key, object.accessor.get(object, primaryKey)); + return _handle.getOrCreateWithPrimaryKey(key, object.accessor.get(object, primaryKey)); } - return realmCore.createRealmObjectWithPrimaryKey(this, key, object.accessor.get(object, primaryKey)); + return _handle.createWithPrimaryKey(key, object.accessor.get(object, primaryKey)); } /// Adds a collection [RealmObject]s to this `Realm`. @@ -345,7 +345,7 @@ class Realm implements Finalizable { } /// Checks whether the `Realm` is in write transaction. - bool get isInTransaction => this.handle.isWritable; + bool get isInTransaction => handle.isWritable; /// Synchronously calls the provided callback inside a write transaction. /// @@ -366,14 +366,14 @@ class Realm implements Finalizable { /// Begins a write transaction for this [Realm]. Transaction beginWrite() { - this.handle.beginWrite(); + handle.beginWrite(); return Transaction._(this); } /// Asynchronously begins a write transaction for this [Realm]. You can supply a /// [CancellationToken] to cancel the operation. Future beginWriteAsync([CancellationToken? cancellationToken]) async { - await this.handle.beginWriteAsync(cancellationToken); + await handle.beginWriteAsync(cancellationToken); return Transaction._(this); } @@ -404,18 +404,18 @@ class Realm implements Finalizable { } _schemaCallbackHandle?.release(); - this.handle.close(); + handle.close(); handle.release(); } /// Checks whether the `Realm` is closed. - bool get isClosed => _handle.released || this.handle.isClosed; + bool get isClosed => _handle.released || handle.isClosed; /// Fast lookup for a [RealmObject] with the specified [primaryKey]. T? find(Object? primaryKey) { final metadata = _metadata.getByType(T); - final handle = realmCore.find(this, metadata.classKey, primaryKey); + final handle = _handle.find(metadata.classKey, primaryKey); if (handle == null) { return null; } @@ -466,7 +466,7 @@ class Realm implements Finalizable { return this; } - return Realm._(config, this.handle.freeze()); + return Realm._(config, handle.freeze()); } WeakReference? _subscriptions; @@ -480,7 +480,7 @@ class Realm implements Finalizable { var result = _subscriptions?.target; if (result == null || result.handle.released) { - result = SubscriptionSetInternal.create(this, this.handle.subscriptions); + result = SubscriptionSetInternal.create(this, handle.subscriptions); result.handle.refresh(); _subscriptions = WeakReference(result); } @@ -500,7 +500,7 @@ class Realm implements Finalizable { var result = _syncSession?.target; if (result == null || result.handle.released) { - result = SessionInternal.create(this.handle.getSession()); + result = SessionInternal.create(handle.getSession()); _syncSession = WeakReference(result); } @@ -583,7 +583,7 @@ class Realm implements Finalizable { throw RealmError("Copying a Realm is not allowed within a write transaction or during migration."); } - this.handle.writeCopy(config); + handle.writeCopy(config); } /// Update the `Realm` instance and outstanding objects to point to the most recent persisted version. @@ -593,7 +593,7 @@ class Realm implements Finalizable { /// Typically you don't need to call this method since Realm has auto-refresh built-in. /// Note that this may return `true` even if no data has actually changed. bool refresh() { - return this.handle.refresh(); + return handle.refresh(); } /// Returns a [Future] that will complete when the `Realm` is refreshed to the version which is the @@ -601,7 +601,7 @@ class Realm implements Finalizable { /// /// Note that this may return `true` even if no data has actually changed. Future refreshAsync() async { - return this.handle.refreshAsync(); + return handle.refreshAsync(); } /// Allows listening for schema changes on this Realm. Only dynamic and synchronized @@ -963,7 +963,7 @@ class DynamicRealm { RealmObject? find(String className, Object primaryKey) { final metadata = _realm._metadata.getByName(className); - final handle = realmCore.find(_realm, metadata.classKey, primaryKey); + final handle = _realm.handle.find(metadata.classKey, primaryKey); if (handle == null) { return null; } From 91c52291f3ddf50bf0441751fe1faa208cc0979c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Sat, 13 Apr 2024 15:46:28 +0200 Subject: [PATCH 25/68] Drop superfluous this. --- analysis_options.yaml | 1 - packages/realm_dart/lib/src/results.dart | 6 +++--- packages/realm_dart/lib/src/user.dart | 18 +++++++++--------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index dc3d7cd3d..16bcf0407 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -19,7 +19,6 @@ linter: rules: avoid_relative_lib_imports: false package_api_docs: true - dangling_library_doc_comments: false # For more information about the core and recommended set of lints, see # https://dart.dev/go/core-lints diff --git a/packages/realm_dart/lib/src/results.dart b/packages/realm_dart/lib/src/results.dart index 8d2f54ef8..da97d3ff4 100644 --- a/packages/realm_dart/lib/src/results.dart +++ b/packages/realm_dart/lib/src/results.dart @@ -29,7 +29,7 @@ class RealmResults extends Iterable with RealmEntity imple } /// Gets a value indicating whether this collection is still valid to use. - bool get isValid => this.handle.isValid(); + bool get isValid => handle.isValid(); /// Returns the element of type `T` at the specified [index]. T operator [](int index) => elementAt(index); @@ -81,7 +81,7 @@ class RealmResults extends Iterable with RealmEntity imple if (start < 0) start = 0; start += _skipOffset; - final index = this.handle.find(element); + final index = handle.find(element); return index < start ? -1 : index; // to align with dart list semantics } @@ -110,7 +110,7 @@ class RealmResults extends Iterable with RealmEntity imple /// The number of values in this `Results` collection. @override - int get length => this.handle.count - _skipOffset; + int get length => handle.count - _skipOffset; @override T get first { diff --git a/packages/realm_dart/lib/src/user.dart b/packages/realm_dart/lib/src/user.dart index 765bf5054..1e1c9996d 100644 --- a/packages/realm_dart/lib/src/user.dart +++ b/packages/realm_dart/lib/src/user.dart @@ -61,49 +61,49 @@ class User { /// The current state of this [User]. UserState get state { - return this.handle.state; + return handle.state; } /// Get this [User]'s id on MongoDB Atlas. String get id { - return this.handle.id; + return handle.id; } /// Gets a collection of all identities associated with this [User]. List get identities { - return this.handle.identities; + return handle.identities; } /// Removes the [User]'s local credentials. This will also close any associated Sessions. Future logOut() async { - return await this.handle.logOut(); + return await handle.logOut(); } /// Gets an unique identifier for the current device. String? get deviceId { - return this.handle.deviceId; + return handle.deviceId; } /// Gets the profile information for this [User]. UserProfile get profile { - return this.handle.profileData; + return handle.profileData; } /// Gets the refresh token for this [User]. This is the user's credential for /// accessing [Atlas App Services](https://www.mongodb.com/docs/atlas/app-services/) and should be treated as sensitive data. String get refreshToken { - return this.handle.refreshToken; + return handle.refreshToken; } /// Gets the access token for this [User]. This is the user's credential for /// accessing [Atlas App Services](https://www.mongodb.com/docs/atlas/app-services/) and should be treated as sensitive data. String get accessToken { - return this.handle.accessToken; + return handle.accessToken; } /// The custom user data associated with this [User]. dynamic get customData { - final data = this.handle.customData; + final data = handle.customData; if (data == null) { return null; } From 3265692aa9d1341a58b177fc9d3531227659baef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Sat, 13 Apr 2024 16:16:13 +0200 Subject: [PATCH 26/68] Refactor AppHandle --- packages/realm_dart/lib/src/app.dart | 26 +- .../lib/src/cli/common/archive.dart | 2 + .../realm_dart/lib/src/configuration.dart | 6 +- packages/realm_dart/lib/src/credentials.dart | 14 +- .../realm_dart/lib/src/native/app_handle.dart | 517 +++++++++++ .../realm_dart/lib/src/native/realm_core.dart | 804 ++++-------------- packages/realm_dart/lib/src/subscription.dart | 2 +- packages/realm_dart/lib/src/user.dart | 7 +- packages/realm_dart/test/app_test.dart | 2 +- packages/realm_dart/test/realm_test.dart | 4 +- 10 files changed, 730 insertions(+), 654 deletions(-) create mode 100644 packages/realm_dart/lib/src/native/app_handle.dart diff --git a/packages/realm_dart/lib/src/app.dart b/packages/realm_dart/lib/src/app.dart index b0025e7a2..9a7d066d6 100644 --- a/packages/realm_dart/lib/src/app.dart +++ b/packages/realm_dart/lib/src/app.dart @@ -7,7 +7,7 @@ import 'dart:io'; import 'dart:isolate'; import 'package:meta/meta.dart'; -import 'package:path/path.dart' as _path; +import 'package:path/path.dart' as path; import '../realm.dart'; import 'credentials.dart'; @@ -125,7 +125,7 @@ class AppConfiguration { this.maxConnectionTimeout = const Duration(minutes: 2), HttpClient? httpClient, }) : baseUrl = baseUrl ?? Uri.parse(realmCore.getDefaultBaseUrl()), - baseFilePath = baseFilePath ?? Directory(_path.dirname(Configuration.defaultRealmPath)), + baseFilePath = baseFilePath ?? Directory(path.dirname(Configuration.defaultRealmPath)), httpClient = httpClient ?? _defaultClient { if (appId == '') { throw RealmException('Supplied appId must be a non-empty value'); @@ -144,7 +144,7 @@ class App implements Finalizable { /// The id of this application. This is the same as the appId in the [AppConfiguration] used to /// create this [App]. - String get id => realmCore.appGetId(this); + String get id => this.handle.id; /// Create an app with a particular [AppConfiguration]. This constructor should only be used on the main isolate and, /// ideally, only once as soon as the app starts. @@ -171,18 +171,18 @@ class App implements Finalizable { static AppHandle _createApp(AppConfiguration configuration) { configuration.baseFilePath.createSync(recursive: true); - return realmCore.createApp(configuration); + return AppHandle(configuration); } /// Logs in a user with the given credentials. Future logIn(Credentials credentials) async { - var userHandle = await realmCore.logIn(this, credentials); + var userHandle = await handle.logIn(credentials); return UserInternal.create(userHandle, this); } /// Gets the currently logged in [User]. If none exists, `null` is returned. User? get currentUser { - final userHandle = realmCore.getCurrentUser(_handle); + final userHandle = _handle.currentUser; if (userHandle == null) { return null; } @@ -191,22 +191,22 @@ class App implements Finalizable { /// Gets all currently logged in users. Iterable get users { - return realmCore.getUsers(this).map((handle) => UserInternal.create(handle, this)); + return handle.users.map((handle) => UserInternal.create(handle, this)); } /// Removes a [user] and their local data from the device. If the user is logged in, they will be logged out in the process. Future removeUser(User user) async { - return await realmCore.removeUser(this, user); + return await handle.removeUser(user.handle); } /// Deletes a user and all its data from the device as well as the server. Future deleteUser(User user) async { - return await realmCore.deleteUser(this, user); + return await handle.deleteUser(user.handle); } /// Switches the [currentUser] to the one specified in [user]. void switchUser(User user) { - realmCore.switchUser(this, user); + handle.switchUser(user.handle); } /// Provide a hint to this app's sync client to reconnect. @@ -214,7 +214,7 @@ class App implements Finalizable { /// /// The sync client will always attempt to reconnect eventually, this is just a hint. void reconnect() { - realmCore.reconnect(this); + handle.reconnect(); } /// Returns the current value of the base URL used to communicate with the server. @@ -223,7 +223,7 @@ class App implements Finalizable { /// be updated with the new value until that operation has completed. @experimental Uri get baseUrl { - return Uri.parse(realmCore.getBaseUrl(this)); + return Uri.parse(handle.baseUrl); } /// Temporarily overrides the [baseUrl] value from [AppConfiguration] with a new [baseUrl] value @@ -237,7 +237,7 @@ class App implements Finalizable { /// The App will revert to using the value in [AppConfiguration] when it is restarted. @experimental Future updateBaseUrl(Uri? baseUrl) async { - return await realmCore.updateBaseUrl(this, baseUrl); + return await handle.updateBaseUrl(baseUrl); } /// Returns an instance of [EmailPasswordAuthProvider] diff --git a/packages/realm_dart/lib/src/cli/common/archive.dart b/packages/realm_dart/lib/src/cli/common/archive.dart index 23ab1dcbb..cb0c34061 100644 --- a/packages/realm_dart/lib/src/cli/common/archive.dart +++ b/packages/realm_dart/lib/src/cli/common/archive.dart @@ -2,6 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 /// +library; + import 'dart:io'; import 'package:tar/tar.dart'; import 'package:path/path.dart' as path; diff --git a/packages/realm_dart/lib/src/configuration.dart b/packages/realm_dart/lib/src/configuration.dart index 5084bbac6..5d8c7abcd 100644 --- a/packages/realm_dart/lib/src/configuration.dart +++ b/packages/realm_dart/lib/src/configuration.dart @@ -7,10 +7,12 @@ import 'dart:io'; // ignore: no_leading_underscores_for_library_prefixes import 'package:path/path.dart' as _path; + +import 'app.dart'; +import 'init.dart'; import 'logging.dart'; import 'native/realm_core.dart'; import 'realm_class.dart'; -import 'init.dart'; import 'user.dart'; /// The signature of a callback used to determine if compaction @@ -653,7 +655,7 @@ class ClientResetError extends SyncError { throw RealmException("Missing `originalFilePath`"); } - return realmCore.immediatelyRunFileActions(_app!, originalFilePath!); + return _app!.handle.immediatelyRunFileActions(originalFilePath!); } } diff --git a/packages/realm_dart/lib/src/credentials.dart b/packages/realm_dart/lib/src/credentials.dart index 21f2f20d8..d141a6e3d 100644 --- a/packages/realm_dart/lib/src/credentials.dart +++ b/packages/realm_dart/lib/src/credentials.dart @@ -123,38 +123,38 @@ class EmailPasswordAuthProvider implements Finalizable { /// /// Successful completion indicates that the user has been created on the server and can now be logged in with [Credentials.emailPassword()]. Future registerUser(String email, String password) async { - return realmCore.appEmailPasswordRegisterUser(app, email, password); + return app.handle.registerUser(email, password); } /// Confirms a user with the given token and token id. These are typically included in the registration email. Future confirmUser(String token, String tokenId) { - return realmCore.emailPasswordConfirmUser(app, token, tokenId); + return app.handle.confirmUser(token, tokenId); } /// Resend the confirmation email for a user to the given email. Future resendUserConfirmation(String email) { - return realmCore.emailPasswordResendUserConfirmation(app, email); + return app.handle.resendConfirmation(email); } /// Completes the reset password procedure by providing the desired new [password] using the /// password reset [token] and [tokenId] that were emailed to a user. Future completeResetPassword(String password, String token, String tokenId) { - return realmCore.emailPasswordCompleteResetPassword(app, password, token, tokenId); + return app.handle.completeResetPassword(password, token, tokenId); } /// Sends a password reset email. Future resetPassword(String email) { - return realmCore.emailPasswordResetPassword(app, email); + return app.handle.requestResetPassword(email); } /// Calls the reset password function, configured on the server. Future callResetPasswordFunction(String email, String password, {List? functionArgs}) { - return realmCore.emailPasswordCallResetPasswordFunction(app, email, password, functionArgs != null ? jsonEncode(functionArgs) : null); + return app.handle.callResetPasswordFunction(email, password, functionArgs.convert(jsonEncode)); } /// Retries the custom confirmation function on a user for a given email. Future retryCustomConfirmationFunction(String email) { - return realmCore.emailPasswordRetryCustomConfirmationFunction(app, email); + return app.handle.retryCustomConfirmationFunction(email); } } diff --git a/packages/realm_dart/lib/src/native/app_handle.dart b/packages/realm_dart/lib/src/native/app_handle.dart new file mode 100644 index 000000000..bd999ebbd --- /dev/null +++ b/packages/realm_dart/lib/src/native/app_handle.dart @@ -0,0 +1,517 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + +part of 'realm_core.dart'; + +class AppHandle extends HandleBase { + AppHandle._(Pointer pointer) : super(pointer, 16); + + static bool _firstTime = true; + factory AppHandle(AppConfiguration configuration) { + // to avoid caching apps across hot restarts we clear the cache on the first + // time the ctor is called in the root isolate. + if (_firstTime && _isRootIsolate) { + _firstTime = false; + realmLib.realm_clear_cached_apps(); + } + final httpTransportHandle = _createHttpTransport(configuration.httpClient); + final appConfigHandle = _createAppConfig(configuration, httpTransportHandle); + final syncClientConfigHandle = _createSyncClientConfig(configuration); + final realmAppPtr = invokeGetPointer(() => realmLib.realm_app_create_cached(appConfigHandle.pointer, syncClientConfigHandle.pointer)); + return AppHandle._(realmAppPtr); + } + + UserHandle? get currentUser { + return realmLib.realm_app_get_current_user(pointer).convert(UserHandle._); + } + + List get users => using((arena) => _getUsers(arena)); + + List _getUsers(Arena arena, {int expectedSize = 2}) { + final actualCount = arena(); + final usersPtr = arena>(expectedSize); + invokeGetBool(() => realmLib.realm_app_get_all_users(pointer, usersPtr, expectedSize, actualCount)); + + if (expectedSize < actualCount.value) { + // The supplied array was too small - resize it + arena.free(usersPtr); + return _getUsers(arena, expectedSize: actualCount.value); + } + + final result = []; + for (var i = 0; i < actualCount.value; i++) { + result.add(UserHandle._((usersPtr + i).value)); + } + + return result; + } + + Future removeUser(UserHandle user) { + final completer = Completer(); + invokeGetBool( + () => realmLib.realm_app_remove_user( + pointer, + user.pointer, + realmLib.addresses.realm_dart_void_completion_callback, + _createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ), + "Remove user failed", + ); + return completer.future; + } + + void switchUser(UserHandle user) { + using((arena) { + invokeGetBool( + () => realmLib.realm_app_switch_user( + pointer, + user.pointer, + nullptr, + ), + "Switch user failed", + ); + }); + } + + void reconnect() => realmLib.realm_app_sync_client_reconnect(pointer); + + String get baseUrl { + final customDataPtr = realmLib.realm_app_get_base_url(pointer); + return customDataPtr.cast().toRealmDartString(freeRealmMemory: true)!; + } + + Future updateBaseUrl(Uri? baseUrl) { + final completer = Completer(); + using((arena) { + invokeGetBool( + () => realmLib.realm_app_update_base_url( + pointer, + baseUrl.toString().toCharPtr(arena), + realmLib.addresses.realm_dart_void_completion_callback, + _createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ), + "Update base URL failed", + ); + }); + return completer.future; + } + + Future refreshCustomData(UserHandle user) { + final completer = Completer(); + invokeGetBool( + () => realmLib.realm_app_refresh_custom_data( + pointer, + user.pointer, + realmLib.addresses.realm_dart_void_completion_callback, + _createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ), + "Refresh custom data failed", + ); + return completer.future; + } + + Future linkCredentials(UserHandle user, RealmAppCredentialsHandle credentials) { + final completer = Completer(); + invokeGetBool( + () => realmLib.realm_app_link_user( + pointer, + user.pointer, + credentials.pointer, + realmLib.addresses.realm_dart_user_completion_callback, + _createAsyncUserCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ), + "Link credentials failed", + ); + return completer.future; + } + + String get id { + return realmLib.realm_app_get_app_id(pointer).cast().toRealmDartString()!; + } + + Future logIn(Credentials credentials) async { + final completer = Completer(); + invokeGetBool( + () => realmLib.realm_app_log_in_with_credentials( + pointer, + credentials.handle.pointer, + realmLib.addresses.realm_dart_user_completion_callback, + _createAsyncUserCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ), + "Login failed", + ); + return await completer.future; + } + + Future registerUser(String email, String password) { + final completer = Completer(); + using((arena) { + invokeGetBool( + () => realmLib.realm_app_email_password_provider_client_register_email( + pointer, + email.toCharPtr(arena), + password.toRealmString(arena).ref, + realmLib.addresses.realm_dart_void_completion_callback, + _createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ), + ); + }); + return completer.future; + } + + Future confirmUser(String token, String tokenId) async { + final completer = Completer(); + using((arena) { + invokeGetBool( + () => realmLib.realm_app_email_password_provider_client_confirm_user( + pointer, + token.toCharPtr(arena), + tokenId.toCharPtr(arena), + realmLib.addresses.realm_dart_void_completion_callback, + _createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ), + ); + }); + return await completer.future; + } + + Future resendConfirmation(String email) { + final completer = Completer(); + using((arena) { + invokeGetBool( + () => realmLib.realm_app_email_password_provider_client_resend_confirmation_email( + pointer, + email.toCharPtr(arena), + realmLib.addresses.realm_dart_void_completion_callback, + _createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ), + ); + }); + return completer.future; + } + + Future completeResetPassword(String password, String token, String tokenId) { + final completer = Completer(); + using((arena) { + invokeGetBool( + () => realmLib.realm_app_email_password_provider_client_reset_password( + pointer, + password.toRealmString(arena).ref, + token.toCharPtr(arena), + tokenId.toCharPtr(arena), + realmLib.addresses.realm_dart_void_completion_callback, + _createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ), + ); + }); + return completer.future; + } + + Future requestResetPassword(String email) { + final completer = Completer(); + using((arena) { + invokeGetBool( + () => realmLib.realm_app_email_password_provider_client_send_reset_password_email( + pointer, + email.toCharPtr(arena), + realmLib.addresses.realm_dart_void_completion_callback, + _createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ), + ); + }); + return completer.future; + } + + Future callResetPasswordFunction(String email, String password, String? argsAsJSON) { + final completer = Completer(); + using((arena) { + invokeGetBool( + () => realmLib.realm_app_email_password_provider_client_call_reset_password_function( + pointer, + email.toCharPtr(arena), + password.toRealmString(arena).ref, + argsAsJSON != null ? argsAsJSON.toCharPtr(arena) : nullptr, + realmLib.addresses.realm_dart_void_completion_callback, + _createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ), + ); + }); + return completer.future; + } + + Future retryCustomConfirmationFunction(String email) { + final completer = Completer(); + using((arena) { + invokeGetBool( + () => realmLib.realm_app_email_password_provider_client_retry_custom_confirmation( + pointer, + email.toCharPtr(arena), + realmLib.addresses.realm_dart_void_completion_callback, + _createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ), + ); + }); + return completer.future; + } + + Future logOut(UserHandle? user) { + final completer = Completer(); + if (user == null) { + invokeGetBool( + () => realmLib.realm_app_log_out_current_user( + pointer, + realmLib.addresses.realm_dart_void_completion_callback, + _createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ), + "Logout failed", + ); + } else { + invokeGetBool( + () => realmLib.realm_app_log_out( + pointer, + user.pointer, + realmLib.addresses.realm_dart_void_completion_callback, + _createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ), + "Logout failed", + ); + } + return completer.future; + } + + Future deleteUser(UserHandle user) { + final completer = Completer(); + invokeGetBool( + () => realmLib.realm_app_delete_user( + pointer, + user.pointer, + realmLib.addresses.realm_dart_void_completion_callback, + _createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ), + "Delete user failed", + ); + return completer.future; + } + + bool immediatelyRunFileActions(String realmPath) { + return using((arena) { + final didRun = arena(); + invokeGetBool( + () => realmLib.realm_sync_immediately_run_file_actions( + pointer, + realmPath.toCharPtr(arena), + didRun, + ), + "An error occurred while resetting the Realm. Check if the file is in use: '$realmPath'", + ); + return didRun.value; + }); + } +} + +// TODO: +// We need a pure Dart equivalent of: +// ```dart +// ServiceBinding.rootIsolateToken != null +// ``` +// to get rid of this hack. +final bool _isRootIsolate = Isolate.current.debugName == 'main'; + +RealmHttpTransportHandle _createHttpTransport(HttpClient httpClient) { + final requestCallback = Pointer.fromFunction)>(_requestCallback); + final requestCallbackUserdata = realmLib.realm_dart_userdata_async_new(httpClient, requestCallback.cast(), scheduler.handle.pointer); + return RealmHttpTransportHandle._(realmLib.realm_http_transport_new( + realmLib.addresses.realm_dart_http_request_callback, + requestCallbackUserdata.cast(), + realmLib.addresses.realm_dart_userdata_async_free, + )); +} + +void _requestCallback(Object userData, realm_http_request request, Pointer requestContext) { + // + // The request struct only survives until end-of-call, even though + // we explicitly call realm_http_transport_complete_request to + // mark request as completed later. + // + // Therefore we need to copy everything out of request before returning. + // We cannot clone request on the native side with realm_clone, + // since realm_http_request does not inherit from WrapC. + + final client = userData as HttpClient; + + client.connectionTimeout = Duration(milliseconds: request.timeout_ms); + + final url = Uri.parse(request.url.cast().toRealmDartString()!); + + final body = request.body.cast().toRealmDartString(length: request.body_size); + + final headers = {}; + for (int i = 0; i < request.num_headers; ++i) { + final header = request.headers[i]; + final name = header.name.cast().toRealmDartString()!; + final value = header.value.cast().toRealmDartString()!; + headers[name] = value; + } + + _requestCallbackAsync(client, request.method, url, body, headers, requestContext); + // The request struct dies here! +} + +Future _requestCallbackAsync( + HttpClient client, + int requestMethod, + Uri url, + String? body, + Map headers, + Pointer requestContext, +) async { + await using((arena) async { + final responsePointer = arena(); + final responseRef = responsePointer.ref; + final method = _HttpMethod.values[requestMethod]; + + try { + // Build request + late HttpClientRequest request; + + switch (method) { + case _HttpMethod.delete: + request = await client.deleteUrl(url); + break; + case _HttpMethod.put: + request = await client.putUrl(url); + break; + case _HttpMethod.patch: + request = await client.patchUrl(url); + break; + case _HttpMethod.post: + request = await client.postUrl(url); + break; + case _HttpMethod.get: + request = await client.getUrl(url); + break; + } + + for (final header in headers.entries) { + request.headers.add(header.key, header.value); + } + + if (body != null) { + request.add(utf8.encode(body)); + } + + Realm.logger.log(LogLevel.debug, "HTTP Transport: Executing ${method.name} $url"); + + final stopwatch = Stopwatch()..start(); + + // Do the call.. + final response = await request.close(); + + stopwatch.stop(); + Realm.logger.log(LogLevel.debug, "HTTP Transport: Executed ${method.name} $url: ${response.statusCode} in ${stopwatch.elapsedMilliseconds} ms"); + + final responseBody = await response.fold>([], (acc, l) => acc..addAll(l)); // gather response + + // Report back to core + responseRef.status_code = response.statusCode; + responseRef.body = responseBody.toCharPtr(arena); + responseRef.body_size = responseBody.length; + + int headerCnt = 0; + response.headers.forEach((name, values) { + headerCnt += values.length; + }); + + responseRef.headers = arena(headerCnt); + responseRef.num_headers = headerCnt; + + int index = 0; + response.headers.forEach((name, values) { + for (final value in values) { + final headerRef = (responseRef.headers + index).ref; + headerRef.name = name.toCharPtr(arena); + headerRef.value = value.toCharPtr(arena); + index++; + } + }); + + responseRef.custom_status_code = _CustomErrorCode.noError.code; + } on SocketException catch (socketEx) { + Realm.logger.log(LogLevel.warn, "HTTP Transport: SocketException executing ${method.name} $url: $socketEx"); + responseRef.custom_status_code = _CustomErrorCode.timeout.code; + } on HttpException catch (httpEx) { + Realm.logger.log(LogLevel.warn, "HTTP Transport: HttpException executing ${method.name} $url: $httpEx"); + responseRef.custom_status_code = _CustomErrorCode.unknownHttp.code; + } catch (ex) { + Realm.logger.log(LogLevel.error, "HTTP Transport: Exception executing ${method.name} $url: $ex"); + responseRef.custom_status_code = _CustomErrorCode.unknown.code; + } finally { + realmLib.realm_http_transport_complete_request(requestContext, responsePointer); + } + }); +} + +SyncClientConfigHandle _createSyncClientConfig(AppConfiguration configuration) { + return using((arena) { + final handle = SyncClientConfigHandle._(realmLib.realm_sync_client_config_new()); + + realmLib.realm_sync_client_config_set_base_file_path(handle.pointer, configuration.baseFilePath.path.toCharPtr(arena)); + realmLib.realm_sync_client_config_set_metadata_mode(handle.pointer, configuration.metadataPersistenceMode.index); + realmLib.realm_sync_client_config_set_connect_timeout(handle.pointer, configuration.maxConnectionTimeout.inMilliseconds); + if (configuration.metadataEncryptionKey != null && configuration.metadataPersistenceMode == MetadataPersistenceMode.encrypted) { + realmLib.realm_sync_client_config_set_metadata_encryption_key(handle.pointer, configuration.metadataEncryptionKey!.toUint8Ptr(arena)); + } + return handle; + }); +} + +AppConfigHandle _createAppConfig(AppConfiguration configuration, RealmHttpTransportHandle httpTransport) { + return using((arena) { + final appId = configuration.appId.toCharPtr(arena); + final handle = AppConfigHandle._(realmLib.realm_app_config_new(appId, httpTransport.pointer)); + + realmLib.realm_app_config_set_platform_version(handle.pointer, Platform.operatingSystemVersion.toCharPtr(arena)); + + realmLib.realm_app_config_set_sdk(handle.pointer, 'Dart'.toCharPtr(arena)); + realmLib.realm_app_config_set_sdk_version(handle.pointer, libraryVersion.toCharPtr(arena)); + + final deviceName = getDeviceName(); + realmLib.realm_app_config_set_device_name(handle.pointer, deviceName.toCharPtr(arena)); + + final deviceVersion = getDeviceVersion(); + realmLib.realm_app_config_set_device_version(handle.pointer, deviceVersion.toCharPtr(arena)); + + realmLib.realm_app_config_set_framework_name(handle.pointer, (isFlutterPlatform ? 'Flutter' : 'Dart VM').toCharPtr(arena)); + realmLib.realm_app_config_set_framework_version(handle.pointer, Platform.version.toCharPtr(arena)); + + realmLib.realm_app_config_set_base_url(handle.pointer, configuration.baseUrl.toString().toCharPtr(arena)); + + realmLib.realm_app_config_set_default_request_timeout(handle.pointer, configuration.defaultRequestTimeout.inMilliseconds); + + realmLib.realm_app_config_set_bundle_id(handle.pointer, getBundleId().toCharPtr(arena)); + + realmLib.realm_app_config_set_base_file_path(handle.pointer, configuration.baseFilePath.path.toCharPtr(arena)); + realmLib.realm_app_config_set_metadata_mode(handle.pointer, configuration.metadataPersistenceMode.index); + + if (configuration.metadataEncryptionKey != null && configuration.metadataPersistenceMode == MetadataPersistenceMode.encrypted) { + realmLib.realm_app_config_set_metadata_encryption_key(handle.pointer, configuration.metadataEncryptionKey!.toUint8Ptr(arena)); + } + + return handle; + }); +} diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 729c2e2a6..ee9407a57 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -41,6 +41,7 @@ import 'realm_bindings.dart'; import 'realm_library.dart'; // TODO: Use regular +part 'app_handle.dart'; part 'config_handle.dart'; part 'convert.dart'; part 'decimal128.dart'; @@ -77,9 +78,65 @@ final _pluginLib = () { return pluginLib; }(); -_RealmCore realmCore = _RealmCore(); +var realmCore = _RealmCore(); const encryptionKeySize = 64; +String getFilesPath() { + return realmLib.realm_dart_get_files_path().cast().toRealmDartString()!; +} + +String getDeviceName() { + if (Platform.isAndroid || Platform.isIOS) { + return realmLib.realm_dart_get_device_name().cast().toRealmDartString()!; + } + + return ""; +} + +String getDeviceVersion() { + if (Platform.isAndroid || Platform.isIOS) { + return realmLib.realm_dart_get_device_version().cast().toRealmDartString()!; + } + + return ""; +} + +String getRealmLibraryCpuArchitecture() { + return realmLib.realm_get_library_cpu_arch().cast().toDartString(); +} + +String getBundleId() { + readBundleId() { + try { + if (!isFlutterPlatform || Platform.environment.containsKey('FLUTTER_TEST')) { + var pubspecPath = path.join(path.current, 'pubspec.yaml'); + var pubspecFile = File(pubspecPath); + + if (pubspecFile.existsSync()) { + final pubspec = Pubspec.parse(pubspecFile.readAsStringSync()); + return pubspec.name; + } + } + + if (Platform.isAndroid) { + return realmLib.realm_dart_get_bundle_id().cast().toDartString(); + } + + final getBundleIdFunc = _pluginLib.lookupFunction Function(), Pointer Function()>("realm_dart_get_bundle_id"); + final bundleIdPtr = getBundleIdFunc(); + return bundleIdPtr.cast().toDartString(); + } on Exception catch (_) { + //Never fail on bundleId. Use fallback value. + } + + //Fallback value + return "realm_bundle_id"; + } + + String bundleId = readBundleId(); + const salt = [82, 101, 97, 108, 109, 32, 105, 115, 32, 103, 114, 101, 97, 116]; + return base64Encode(sha256.convert([...salt, ...utf8.encode(bundleId)]).bytes); +} void _guardSynchronousCallback(FutureOr Function() callback, Pointer unlockCallbackFunc) async { Pointer user_error = nullptr; @@ -172,6 +229,127 @@ bool initial_data_callback(Pointer userdata, Pointer realmPt return false; } +Pointer _createAsyncUserCallbackUserdata(Completer completer) { + final callback = Pointer.fromFunction< + Void Function( + Pointer, + Pointer, + Pointer, + )>(_app_user_completion_callback); + + final userdata = realmLib.realm_dart_userdata_async_new( + completer, + callback.cast(), + scheduler.handle.pointer, + ); + + return userdata.cast(); +} + +void _app_api_key_completion_callback(Pointer userdata, Pointer apiKey, Pointer error) { + final Completer completer = userdata.toObject(); + if (error != nullptr) { + completer.completeWithAppError(error); + return; + } + completer.complete(apiKey.ref.toDart()); +} + +void _app_api_key_array_completion_callback(Pointer userdata, Pointer apiKey, int size, Pointer error) { + final Completer> completer = userdata.toObject(); + + if (error != nullptr) { + completer.completeWithAppError(error); + return; + } + + final result = []; + for (var i = 0; i < size; i++) { + result.add(apiKey[i].toDart()); + } + + completer.complete(result); +} + +void _app_user_completion_callback(Pointer userdata, Pointer user, Pointer error) { + final Completer completer = userdata.toObject(); + + if (error != nullptr) { + completer.completeWithAppError(error); + return; + } + + user = realmLib.realm_clone(user.cast()).cast(); // take an extra reference to the user object + if (user == nullptr) { + completer.completeError(RealmException("Error while cloning user object.")); + return; + } + + completer.complete(UserHandle._(user.cast())); +} + +void _void_completion_callback(Pointer userdata, Pointer error) { + final Completer completer = userdata.toObject(); + + if (error != nullptr) { + completer.completeWithAppError(error); + return; + } + + completer.complete(); +} + +Pointer _createAsyncCallbackUserdata(Completer completer) { + final callback = Pointer.fromFunction< + Void Function( + Pointer, + Pointer, + )>(_void_completion_callback); + + final userdata = realmLib.realm_dart_userdata_async_new( + completer, + callback.cast(), + scheduler.handle.pointer, + ); + + return userdata.cast(); +} + +Pointer _createAsyncApikeyCallbackUserdata(Completer completer) { + final callback = Pointer.fromFunction< + Void Function( + Pointer, + Pointer, + Pointer, + )>(_app_api_key_completion_callback); + + final userdata = realmLib.realm_dart_userdata_async_new( + completer, + callback.cast(), + scheduler.handle.pointer, + ); + + return userdata.cast(); +} + +Pointer _createAsyncApikeyListCallbackUserdata(Completer> completer) { + final callback = Pointer.fromFunction< + Void Function( + Pointer, + Pointer, + Size count, + Pointer, + )>(_app_api_key_array_completion_callback); + + final userdata = realmLib.realm_dart_userdata_async_new( + completer, + callback.cast(), + scheduler.handle.pointer, + ); + + return userdata.cast(); +} + // All access to Realm Core functionality goes through this class class _RealmCore { // From realm.h. Currently not exported from the shared library @@ -362,30 +540,6 @@ class _RealmCore { }); } - String getFilesPath() { - return realmLib.realm_dart_get_files_path().cast().toRealmDartString()!; - } - - String getDeviceName() { - if (Platform.isAndroid || Platform.isIOS) { - return realmLib.realm_dart_get_device_name().cast().toRealmDartString()!; - } - - return ""; - } - - String getDeviceVersion() { - if (Platform.isAndroid || Platform.isIOS) { - return realmLib.realm_dart_get_device_version().cast().toRealmDartString()!; - } - - return ""; - } - - String getRealmLibraryCpuArchitecture() { - return realmLib.realm_get_library_cpu_arch().cast().toDartString(); - } - RealmObjectMetadata getObjectMetadata(Realm realm, SchemaObject schema) { return using((Arena arena) { final found = arena(); @@ -1244,167 +1398,12 @@ class _RealmCore { }); } - RealmHttpTransportHandle _createHttpTransport(HttpClient httpClient) { - final requestCallback = Pointer.fromFunction)>(_request_callback); - final requestCallbackUserdata = realmLib.realm_dart_userdata_async_new(httpClient, requestCallback.cast(), scheduler.handle.pointer); - return RealmHttpTransportHandle._(realmLib.realm_http_transport_new( - realmLib.addresses.realm_dart_http_request_callback, - requestCallbackUserdata.cast(), - realmLib.addresses.realm_dart_userdata_async_free, - )); - } - - static void _request_callback(Object userData, realm_http_request request, Pointer request_context) { - // - // The request struct only survives until end-of-call, even though - // we explicitly call realm_http_transport_complete_request to - // mark request as completed later. - // - // Therefore we need to copy everything out of request before returning. - // We cannot clone request on the native side with realm_clone, - // since realm_http_request does not inherit from WrapC. - - final client = userData as HttpClient; - - client.connectionTimeout = Duration(milliseconds: request.timeout_ms); - - final url = Uri.parse(request.url.cast().toRealmDartString()!); - - final body = request.body.cast().toRealmDartString(length: request.body_size); - - final headers = {}; - for (int i = 0; i < request.num_headers; ++i) { - final header = request.headers[i]; - final name = header.name.cast().toRealmDartString()!; - final value = header.value.cast().toRealmDartString()!; - headers[name] = value; - } - - _request_callback_async(client, request.method, url, body, headers, request_context); - // The request struct dies here! - } - - static Future _request_callback_async( - HttpClient client, - int requestMethod, - Uri url, - String? body, - Map headers, - Pointer request_context, - ) async { - await using((arena) async { - final response_pointer = arena(); - final responseRef = response_pointer.ref; - final method = _HttpMethod.values[requestMethod]; - - try { - // Build request - late HttpClientRequest request; - - switch (method) { - case _HttpMethod.delete: - request = await client.deleteUrl(url); - break; - case _HttpMethod.put: - request = await client.putUrl(url); - break; - case _HttpMethod.patch: - request = await client.patchUrl(url); - break; - case _HttpMethod.post: - request = await client.postUrl(url); - break; - case _HttpMethod.get: - request = await client.getUrl(url); - break; - } - - for (final header in headers.entries) { - request.headers.add(header.key, header.value); - } - - if (body != null) { - request.add(utf8.encode(body)); - } - - Realm.logger.log(LogLevel.debug, "HTTP Transport: Executing ${method.name} $url"); - - final stopwatch = Stopwatch()..start(); - - // Do the call.. - final response = await request.close(); - - stopwatch.stop(); - Realm.logger.log(LogLevel.debug, "HTTP Transport: Executed ${method.name} $url: ${response.statusCode} in ${stopwatch.elapsedMilliseconds} ms"); - - final responseBody = await response.fold>([], (acc, l) => acc..addAll(l)); // gather response - - // Report back to core - responseRef.status_code = response.statusCode; - responseRef.body = responseBody.toCharPtr(arena); - responseRef.body_size = responseBody.length; - - int headerCnt = 0; - response.headers.forEach((name, values) { - headerCnt += values.length; - }); - - responseRef.headers = arena(headerCnt); - responseRef.num_headers = headerCnt; - - int index = 0; - response.headers.forEach((name, values) { - for (final value in values) { - final headerRef = responseRef.headers.elementAt(index).ref; - headerRef.name = name.toCharPtr(arena); - headerRef.value = value.toCharPtr(arena); - index++; - } - }); - - responseRef.custom_status_code = _CustomErrorCode.noError.code; - } on SocketException catch (socketEx) { - Realm.logger.log(LogLevel.warn, "HTTP Transport: SocketException executing ${method.name} $url: $socketEx"); - responseRef.custom_status_code = _CustomErrorCode.timeout.code; - } on HttpException catch (httpEx) { - Realm.logger.log(LogLevel.warn, "HTTP Transport: HttpException executing ${method.name} $url: $httpEx"); - responseRef.custom_status_code = _CustomErrorCode.unknownHttp.code; - } catch (ex) { - Realm.logger.log(LogLevel.error, "HTTP Transport: Exception executing ${method.name} $url: $ex"); - responseRef.custom_status_code = _CustomErrorCode.unknown.code; - } finally { - realmLib.realm_http_transport_complete_request(request_context, response_pointer); - } - }); - } - void logMessage(LogCategory category, LogLevel logLevel, String message) { return using((arena) { realmLib.realm_dart_log(logLevel.index, category.toString().toCharPtr(arena), message.toCharPtr(arena)); }); } - // TODO: - // We need a pure Dart equivalent of: - // `ServiceBinding.rootIsolateToken != null` - // to get rid of this hack. - final bool _isRootIsolate = Isolate.current.debugName == 'main'; - - static bool _firstTime = true; - AppHandle createApp(AppConfiguration configuration) { - // to avoid caching apps across hot restarts we clear the cache on the first - // call to createApp in the root isolate. - if (_firstTime && _isRootIsolate) { - _firstTime = false; - realmLib.realm_clear_cached_apps(); - } - final httpTransportHandle = _createHttpTransport(configuration.httpClient); - final appConfigHandle = _createAppConfig(configuration, httpTransportHandle); - final realmAppPtr = invokeGetPointer(() => realmLib.realm_app_create_cached(appConfigHandle._pointer)); - - return AppHandle._(realmAppPtr); - } - String getDefaultBaseUrl() { return realmLib.realm_app_get_default_base_url().cast().toRealmDartString()!; } @@ -1417,319 +1416,10 @@ class _RealmCore { }); } - String appGetId(App app) { - return realmLib.realm_app_get_app_id(app.handle.pointer).cast().toRealmDartString()!; - } - - static void _app_user_completion_callback(Pointer userdata, Pointer user, Pointer error) { - final Completer completer = userdata.toObject(); - - if (error != nullptr) { - completer.completeWithAppError(error); - return; - } - - user = realmLib.realm_clone(user.cast()).cast(); // take an extra reference to the user object - if (user == nullptr) { - completer.completeError(RealmException("Error while cloning user object.")); - return; - } - - completer.complete(UserHandle._(user.cast())); - } - - Pointer _createAsyncUserCallbackUserdata(Completer completer) { - final callback = Pointer.fromFunction< - Void Function( - Pointer, - Pointer, - Pointer, - )>(_app_user_completion_callback); - - final userdata = realmLib.realm_dart_userdata_async_new( - completer, - callback.cast(), - scheduler.handle.pointer, - ); - - return userdata.cast(); - } - - Future logIn(App app, Credentials credentials) async { - final completer = Completer(); - final userdata = _createAsyncUserCallbackUserdata(completer); - - invokeGetBool( - () => realmLib.realm_app_log_in_with_credentials( - app.handle.pointer, - credentials.handle.pointer, - realmLib.addresses.realm_dart_user_completion_callback, - userdata, - realmLib.addresses.realm_dart_userdata_async_free, - ), - "Login failed"); - - return await completer.future; - } - - static void _void_completion_callback(Pointer userdata, Pointer error) { - final Completer completer = userdata.toObject(); - - if (error != nullptr) { - completer.completeWithAppError(error); - return; - } - - completer.complete(); - } - - Future appEmailPasswordRegisterUser(App app, String email, String password) { - final completer = Completer(); - using((arena) { - invokeGetBool(() => realmLib.realm_app_email_password_provider_client_register_email( - app.handle.pointer, - email.toCharPtr(arena), - password.toRealmString(arena).ref, - realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - )); - }); - return completer.future; - } - - Future emailPasswordConfirmUser(App app, String token, String tokenId) async { - final completer = Completer(); - using((arena) { - invokeGetBool(() => realmLib.realm_app_email_password_provider_client_confirm_user( - app.handle.pointer, - token.toCharPtr(arena), - tokenId.toCharPtr(arena), - realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - )); - }); - return await completer.future; - } - - Future emailPasswordResendUserConfirmation(App app, String email) { - final completer = Completer(); - using((arena) { - invokeGetBool(() => realmLib.realm_app_email_password_provider_client_resend_confirmation_email( - app.handle.pointer, - email.toCharPtr(arena), - realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - )); - }); - return completer.future; - } - - Future emailPasswordCompleteResetPassword(App app, String password, String token, String tokenId) { - final completer = Completer(); - using((arena) { - invokeGetBool(() => realmLib.realm_app_email_password_provider_client_reset_password( - app.handle.pointer, - password.toRealmString(arena).ref, - token.toCharPtr(arena), - tokenId.toCharPtr(arena), - realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - )); - }); - return completer.future; - } - - Future emailPasswordResetPassword(App app, String email) { - final completer = Completer(); - using((arena) { - invokeGetBool(() => realmLib.realm_app_email_password_provider_client_send_reset_password_email( - app.handle.pointer, - email.toCharPtr(arena), - realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - )); - }); - return completer.future; - } - - Future emailPasswordCallResetPasswordFunction(App app, String email, String password, String? argsAsJSON) { - final completer = Completer(); - using((arena) { - invokeGetBool(() => realmLib.realm_app_email_password_provider_client_call_reset_password_function( - app.handle.pointer, - email.toCharPtr(arena), - password.toRealmString(arena).ref, - argsAsJSON != null ? argsAsJSON.toCharPtr(arena) : nullptr, - realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - )); - }); - return completer.future; - } - - Future emailPasswordRetryCustomConfirmationFunction(App app, String email) { - final completer = Completer(); - using((arena) { - invokeGetBool(() => realmLib.realm_app_email_password_provider_client_retry_custom_confirmation( - app.handle.pointer, - email.toCharPtr(arena), - realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - )); - }); - return completer.future; - } - - UserHandle? getCurrentUser(AppHandle appHandle) { - final userPtr = realmLib.realm_app_get_current_user(appHandle.pointer); - if (userPtr == nullptr) { - return null; - } - return UserHandle._(userPtr); - } - - Future logOut(App application, User? user) { - final completer = Completer(); - if (user == null) { - invokeGetBool( - () => realmLib.realm_app_log_out_current_user( - application.handle.pointer, - realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ), - "Logout failed"); - } else { - invokeGetBool( - () => realmLib.realm_app_log_out( - application.handle.pointer, - user.handle.pointer, - realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ), - "Logout failed"); - } - return completer.future; - } - void clearCachedApps() { realmLib.realm_clear_cached_apps(); } - List getUsers(App app) { - return using((arena) { - return _getUsers(app, arena); - }); - } - - List _getUsers(App app, Arena arena, {int expectedSize = 2}) { - final actualCount = arena(); - final usersPtr = arena>(expectedSize); - invokeGetBool(() => realmLib.realm_app_get_all_users(app.handle.pointer, usersPtr, expectedSize, actualCount)); - - if (expectedSize < actualCount.value) { - // The supplied array was too small - resize it - arena.free(usersPtr); - return _getUsers(app, arena, expectedSize: actualCount.value); - } - - final result = []; - for (var i = 0; i < actualCount.value; i++) { - result.add(UserHandle._(usersPtr.elementAt(i).value)); - } - - return result; - } - - Future removeUser(App app, User user) { - final completer = Completer(); - invokeGetBool( - () => realmLib.realm_app_remove_user( - app.handle.pointer, - user.handle.pointer, - realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ), - "Remove user failed"); - return completer.future; - } - - void switchUser(App application, User user) { - return using((arena) { - invokeGetBool( - () => realmLib.realm_app_switch_user( - application.handle.pointer, - user.handle.pointer, - ), - "Switch user failed"); - }); - } - - void reconnect(App application) { - realmLib.realm_app_sync_client_reconnect( - application.handle.pointer, - ); - } - - String getBaseUrl(App app) { - final customDataPtr = realmLib.realm_app_get_base_url(app.handle.pointer); - return customDataPtr.cast().toRealmDartString(freeRealmMemory: true)!; - } - - Future updateBaseUrl(App app, Uri? baseUrl) { - final completer = Completer(); - using((arena) { - invokeGetBool( - () => realmLib.realm_app_update_base_url( - app.handle._pointer, - baseUrl?.toString().toCharPtr(arena) ?? nullptr, - realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ), - "Update base URL failed"); - }); - return completer.future; - } - - Future userRefreshCustomData(App app, User user) { - final completer = Completer(); - invokeGetBool( - () => realmLib.realm_app_refresh_custom_data( - app.handle.pointer, - user.handle.pointer, - realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ), - "Refresh custom data failed"); - return completer.future; - } - - Future userLinkCredentials(App app, User user, Credentials credentials) { - final completer = Completer(); - invokeGetBool( - () => realmLib.realm_app_link_user( - app.handle.pointer, - user.handle.pointer, - credentials.handle.pointer, - realmLib.addresses.realm_dart_user_completion_callback, - _createAsyncUserCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ), - "Link credentials failed"); - return completer.future; - } - AuthProviderType userGetCredentialsProviderType(Credentials credentials) { final provider = realmLib.realm_auth_credentials_get_provider(credentials.handle.pointer); return AuthProviderTypeInternal.getByValue(provider); @@ -1849,39 +1539,6 @@ class _RealmCore { } } - String getBundleId() { - readBundleId() { - try { - if (!isFlutterPlatform || Platform.environment.containsKey('FLUTTER_TEST')) { - var pubspecPath = path.join(path.current, 'pubspec.yaml'); - var pubspecFile = File(pubspecPath); - - if (pubspecFile.existsSync()) { - final pubspec = Pubspec.parse(pubspecFile.readAsStringSync()); - return pubspec.name; - } - } - - if (Platform.isAndroid) { - return realmLib.realm_dart_get_bundle_id().cast().toDartString(); - } - - final getBundleIdFunc = _pluginLib.lookupFunction Function(), Pointer Function()>("realm_dart_get_bundle_id"); - final bundleIdPtr = getBundleIdFunc(); - return bundleIdPtr.cast().toDartString(); - } on Exception catch (_) { - //Never fail on bundleId. Use fallback value. - } - - //Fallback value - return "realm_bundle_id"; - } - - String bundleId = readBundleId(); - const salt = [82, 101, 97, 108, 109, 32, 105, 115, 32, 103, 114, 101, 97, 116]; - return base64Encode(sha256.convert([...salt, ...utf8.encode(bundleId)]).bytes); - } - String _getAppDirectoryFromPlugin() { assert(isFlutterPlatform); @@ -1923,20 +1580,6 @@ class _RealmCore { } } - Future deleteUser(App app, User user) { - final completer = Completer(); - invokeGetBool( - () => realmLib.realm_app_delete_user( - app.handle.pointer, - user.handle.pointer, - realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ), - "Delete user failed"); - return completer.future; - } - ResultsHandle resolveResults(RealmResults realmResults, Realm frozenRealm) => realmResults.handle.resolveIn(frozenRealm.handle); ObjectHandle? resolveObject(RealmObjectBase object, Realm frozenRealm) { @@ -1971,31 +1614,6 @@ class _RealmCore { }); } - static void _app_api_key_completion_callback(Pointer userdata, Pointer apiKey, Pointer error) { - final Completer completer = userdata.toObject(); - if (error != nullptr) { - completer.completeWithAppError(error); - return; - } - completer.complete(apiKey.ref.toDart()); - } - - static void _app_api_key_array_completion_callback(Pointer userdata, Pointer apiKey, int size, Pointer error) { - final Completer> completer = userdata.toObject(); - - if (error != nullptr) { - completer.completeWithAppError(error); - return; - } - - final result = []; - for (var i = 0; i < size; i++) { - result.add(apiKey[i].toDart()); - } - - completer.complete(result); - } - Future createApiKey(User user, String name) { return using((Arena arena) { final namePtr = name.toCharPtr(arena); @@ -2062,57 +1680,6 @@ class _RealmCore { }); } - Pointer _createAsyncCallbackUserdata(Completer completer) { - final callback = Pointer.fromFunction< - Void Function( - Pointer, - Pointer, - )>(_void_completion_callback); - - final userdata = realmLib.realm_dart_userdata_async_new( - completer, - callback.cast(), - scheduler.handle.pointer, - ); - - return userdata.cast(); - } - - Pointer _createAsyncApikeyCallbackUserdata(Completer completer) { - final callback = Pointer.fromFunction< - Void Function( - Pointer, - Pointer, - Pointer, - )>(_app_api_key_completion_callback); - - final userdata = realmLib.realm_dart_userdata_async_new( - completer, - callback.cast(), - scheduler.handle.pointer, - ); - - return userdata.cast(); - } - - Pointer _createAsyncApikeyListCallbackUserdata(Completer> completer) { - final callback = Pointer.fromFunction< - Void Function( - Pointer, - Pointer, - Size count, - Pointer, - )>(_app_api_key_array_completion_callback); - - final userdata = realmLib.realm_dart_userdata_async_new( - completer, - callback.cast(), - scheduler.handle.pointer, - ); - - return userdata.cast(); - } - Future disableApiKey(User user, ObjectId objectId) { return using((Arena arena) { final completer = Completer(); @@ -2194,15 +1761,6 @@ class _RealmCore { }); } - bool immediatelyRunFileActions(App app, String realmPath) { - return using((arena) { - final out_did_run = arena(); - invokeGetBool(() => realmLib.realm_sync_immediately_run_file_actions(app.handle.pointer, realmPath.toCharPtr(arena), out_did_run), - "An error occurred while resetting the Realm. Check if the file is in use: '$realmPath'"); - return out_did_run.value; - }); - } - void _createCollection(Realm realm, RealmValue value, Pointer Function() createList, Pointer Function() createMap) { CollectionHandleBase? collectionHandle; try { @@ -2325,10 +1883,6 @@ class SyncClientConfigHandle extends HandleBase { SyncClientConfigHandle._(Pointer pointer) : super(pointer, 8); } -class AppHandle extends HandleBase { - AppHandle._(Pointer pointer) : super(pointer, 16); -} - class RealmAsyncOpenTaskHandle extends HandleBase { RealmAsyncOpenTaskHandle._(Pointer pointer) : super(pointer, 32); } diff --git a/packages/realm_dart/lib/src/subscription.dart b/packages/realm_dart/lib/src/subscription.dart index 880b75208..ef86b2a91 100644 --- a/packages/realm_dart/lib/src/subscription.dart +++ b/packages/realm_dart/lib/src/subscription.dart @@ -226,7 +226,7 @@ final class MutableSubscriptionSet extends SubscriptionSet { @override MutableSubscriptionSetHandle get _handle => super._handle as MutableSubscriptionSetHandle; - MutableSubscriptionSet._(Realm realm, MutableSubscriptionSetHandle handle) : super._(realm, handle); + MutableSubscriptionSet._(super.realm, MutableSubscriptionSetHandle super.handle) : super._(); @override void update(void Function(MutableSubscriptionSet mutableSubscriptions) action) { diff --git a/packages/realm_dart/lib/src/user.dart b/packages/realm_dart/lib/src/user.dart index 1e1c9996d..a84809dd7 100644 --- a/packages/realm_dart/lib/src/user.dart +++ b/packages/realm_dart/lib/src/user.dart @@ -5,9 +5,10 @@ import 'dart:async'; import 'dart:convert'; import 'dart:ffi'; +import 'app.dart'; +import 'credentials.dart'; import 'native/realm_core.dart'; import 'realm_class.dart'; -import './app.dart'; /// Describes the changes to a [User] instance - for example when the access token is updated or the user state changes. /// Right now, this only conveys information that the user has changed, but in the future it will be enhanced by adding @@ -113,7 +114,7 @@ class User { /// Refreshes the custom data for a this [User]. Future refreshCustomData() async { - await realmCore.userRefreshCustomData(app, this); + await app.handle.refreshCustomData(handle); return customData; } @@ -135,7 +136,7 @@ class User { /// await user.linkCredentials(Credentials.emailPassword("username", "password")); /// ``` Future linkCredentials(Credentials credentials) async { - final userHandle = await realmCore.userLinkCredentials(app, this, credentials); + final userHandle = await app.handle.linkCredentials(handle, credentials.handle); return UserInternal.create(userHandle, app); } diff --git a/packages/realm_dart/test/app_test.dart b/packages/realm_dart/test/app_test.dart index b543c0946..6ed88d120 100644 --- a/packages/realm_dart/test/app_test.dart +++ b/packages/realm_dart/test/app_test.dart @@ -322,7 +322,7 @@ void main() { final text = isFlutterPlatform ? "realm_tests" : "realm_dart"; const salt = [82, 101, 97, 108, 109, 32, 105, 115, 32, 103, 114, 101, 97, 116]; final expected = base64Encode(sha256.convert([...salt, ...utf8.encode(text)]).bytes); - expect(realmCore.getBundleId(), expected); + expect(getBundleId(), expected); }); test('app.getById without apps returns null', () { diff --git a/packages/realm_dart/test/realm_test.dart b/packages/realm_dart/test/realm_test.dart index 398f2d221..befa172e6 100644 --- a/packages/realm_dart/test/realm_test.dart +++ b/packages/realm_dart/test/realm_test.dart @@ -1844,8 +1844,8 @@ void main() { matcher = isEmpty; } - expect(realmCore.getDeviceName(), matcher); - expect(realmCore.getDeviceVersion(), matcher); + expect(getDeviceName(), matcher); + expect(getDeviceVersion(), matcher); }); test('Realm path with unicode symbols', () { From 516f65ca0dd9944aaa3db6c7a77d8fba358dac70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Sat, 13 Apr 2024 22:24:50 +0200 Subject: [PATCH 27/68] Refactor SchedulerHandle --- packages/realm_dart/lib/src/native/realm_core.dart | 9 --------- .../realm_dart/lib/src/native/scheduler_handle.dart | 11 +++++++++++ packages/realm_dart/lib/src/scheduler.dart | 3 ++- 3 files changed, 13 insertions(+), 10 deletions(-) create mode 100644 packages/realm_dart/lib/src/native/scheduler_handle.dart diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index ee9407a57..3dabee30d 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -393,11 +393,6 @@ class _RealmCore { }); } - SchedulerHandle createScheduler(int isolateId, int sendPort) { - final schedulerPtr = realmLib.realm_dart_create_scheduler(isolateId, sendPort); - return SchedulerHandle._(schedulerPtr); - } - void invokeScheduler(int workQueue) { final queuePointer = Pointer.fromAddress(workQueue); realmLib.realm_scheduler_perform_work(queuePointer); @@ -1815,10 +1810,6 @@ class _RealmCore { } } -class SchedulerHandle extends HandleBase { - SchedulerHandle._(Pointer pointer) : super(pointer, 24); -} - class _RealmLinkHandle { final int targetKey; final int classKey; diff --git a/packages/realm_dart/lib/src/native/scheduler_handle.dart b/packages/realm_dart/lib/src/native/scheduler_handle.dart new file mode 100644 index 000000000..881e18c1d --- /dev/null +++ b/packages/realm_dart/lib/src/native/scheduler_handle.dart @@ -0,0 +1,11 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + +class SchedulerHandle extends HandleBase { + SchedulerHandle._(Pointer pointer) : super(pointer, 24); + + factory SchedulerHandle(int isolateId, int sendPort) { + final schedulerPtr = realmLib.realm_dart_create_scheduler(isolateId, sendPort); + return SchedulerHandle._(schedulerPtr); + } +} diff --git a/packages/realm_dart/lib/src/scheduler.dart b/packages/realm_dart/lib/src/scheduler.dart index d87a389cd..5ee31931c 100644 --- a/packages/realm_dart/lib/src/scheduler.dart +++ b/packages/realm_dart/lib/src/scheduler.dart @@ -8,6 +8,7 @@ import 'package:realm_dart/src/logging.dart'; import 'native/realm_core.dart'; +import 'native/scheduler_handle.dart'; import 'realm_class.dart'; final _receivePortFinalizer = Finalizer((p) => p.close()); @@ -34,7 +35,7 @@ class Scheduler { // these. _receivePort.handler = Zone.current.bindUnaryCallbackGuarded(_handle); final sendPort = _receivePort.sendPort; - handle = realmCore.createScheduler(Isolate.current.hashCode, sendPort.nativePort); + handle = SchedulerHandle(Isolate.current.hashCode, sendPort.nativePort); } void _handle(dynamic message) { From ac783055aec61fcc042018e896e6b972584990e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Sat, 13 Apr 2024 22:32:43 +0200 Subject: [PATCH 28/68] Move config handles --- .../realm_dart/lib/src/native/app_handle.dart | 24 ++++++++++++++----- .../realm_dart/lib/src/native/realm_core.dart | 12 ---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/packages/realm_dart/lib/src/native/app_handle.dart b/packages/realm_dart/lib/src/native/app_handle.dart index bd999ebbd..432020bd0 100644 --- a/packages/realm_dart/lib/src/native/app_handle.dart +++ b/packages/realm_dart/lib/src/native/app_handle.dart @@ -332,10 +332,14 @@ class AppHandle extends HandleBase { // to get rid of this hack. final bool _isRootIsolate = Isolate.current.debugName == 'main'; -RealmHttpTransportHandle _createHttpTransport(HttpClient httpClient) { +class _HttpTransportHandle extends HandleBase { + _HttpTransportHandle._(Pointer pointer) : super(pointer, 24); +} + +_HttpTransportHandle _createHttpTransport(HttpClient httpClient) { final requestCallback = Pointer.fromFunction)>(_requestCallback); final requestCallbackUserdata = realmLib.realm_dart_userdata_async_new(httpClient, requestCallback.cast(), scheduler.handle.pointer); - return RealmHttpTransportHandle._(realmLib.realm_http_transport_new( + return _HttpTransportHandle._(realmLib.realm_http_transport_new( realmLib.addresses.realm_dart_http_request_callback, requestCallbackUserdata.cast(), realmLib.addresses.realm_dart_userdata_async_free, @@ -466,9 +470,13 @@ Future _requestCallbackAsync( }); } -SyncClientConfigHandle _createSyncClientConfig(AppConfiguration configuration) { +class _SyncClientConfigHandle extends HandleBase { + _SyncClientConfigHandle._(Pointer pointer) : super(pointer, 8); +} + +_SyncClientConfigHandle _createSyncClientConfig(AppConfiguration configuration) { return using((arena) { - final handle = SyncClientConfigHandle._(realmLib.realm_sync_client_config_new()); + final handle = _SyncClientConfigHandle._(realmLib.realm_sync_client_config_new()); realmLib.realm_sync_client_config_set_base_file_path(handle.pointer, configuration.baseFilePath.path.toCharPtr(arena)); realmLib.realm_sync_client_config_set_metadata_mode(handle.pointer, configuration.metadataPersistenceMode.index); @@ -480,10 +488,14 @@ SyncClientConfigHandle _createSyncClientConfig(AppConfiguration configuration) { }); } -AppConfigHandle _createAppConfig(AppConfiguration configuration, RealmHttpTransportHandle httpTransport) { +class _AppConfigHandle extends HandleBase { + _AppConfigHandle._(Pointer pointer) : super(pointer, 8); +} + +_AppConfigHandle _createAppConfig(AppConfiguration configuration, _HttpTransportHandle httpTransport) { return using((arena) { final appId = configuration.appId.toCharPtr(arena); - final handle = AppConfigHandle._(realmLib.realm_app_config_new(appId, httpTransport.pointer)); + final handle = _AppConfigHandle._(realmLib.realm_app_config_new(appId, httpTransport.pointer)); realmLib.realm_app_config_set_platform_version(handle.pointer, Platform.operatingSystemVersion.toCharPtr(arena)); diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 3dabee30d..87c06be80 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -1862,18 +1862,6 @@ class RealmAppCredentialsHandle extends HandleBase { RealmAppCredentialsHandle._(Pointer pointer) : super(pointer, 16); } -class RealmHttpTransportHandle extends HandleBase { - RealmHttpTransportHandle._(Pointer pointer) : super(pointer, 24); -} - -class AppConfigHandle extends HandleBase { - AppConfigHandle._(Pointer pointer) : super(pointer, 8); -} - -class SyncClientConfigHandle extends HandleBase { - SyncClientConfigHandle._(Pointer pointer) : super(pointer, 8); -} - class RealmAsyncOpenTaskHandle extends HandleBase { RealmAsyncOpenTaskHandle._(Pointer pointer) : super(pointer, 32); } From eb6037586997b9c426ebbcea907c74ba38b4150b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Sat, 13 Apr 2024 23:02:58 +0200 Subject: [PATCH 29/68] Refactor SessionHandle --- .../lib/src/native/object_handle.dart | 36 +++++++ .../realm_dart/lib/src/native/realm_core.dart | 91 +----------------- .../lib/src/native/scheduler_handle.dart | 6 ++ .../lib/src/native/session_handle.dart | 94 +++++++++++++++++++ packages/realm_dart/lib/src/realm_class.dart | 2 +- packages/realm_dart/lib/src/session.dart | 16 ++-- 6 files changed, 147 insertions(+), 98 deletions(-) create mode 100644 packages/realm_dart/lib/src/native/session_handle.dart diff --git a/packages/realm_dart/lib/src/native/object_handle.dart b/packages/realm_dart/lib/src/native/object_handle.dart index 6310f3f50..5864fffee 100644 --- a/packages/realm_dart/lib/src/native/object_handle.dart +++ b/packages/realm_dart/lib/src/native/object_handle.dart @@ -12,4 +12,40 @@ class ObjectHandle extends RootedHandleBase { } int getClassKey() => realmLib.realm_object_get_table(pointer); + +/* + Object? getProperty(int propertyKey) { + return using((Arena arena) { + final realmValue = arena(); + invokeGetBool(() => realmLib.realm_get_value(pointer, propertyKey, realmValue)); + return realmValue.toDartValue( + object.realm, + () => realmLib.realm_get_list(pointer, propertyKey), + () => realmLib.realm_get_dictionary(pointer, propertyKey), + ); + }); + } +*/ + + void setProperty(int propertyKey, Object? value, bool isDefault) { + using((Arena arena) { + final realmValue = _toRealmValue(value, arena); + invokeGetBool(() => realmLib.realm_set_value(pointer, propertyKey, realmValue.ref, isDefault)); + }); + } + +/* + void objectSetCollection(int propertyKey, RealmValue value) { + _createCollection(object.realm, value, () => realmLib.realm_set_list(pointer, propertyKey), + () => realmLib.realm_set_dictionary(pointer, propertyKey)); + } +*/ + + String objectToString() { + return realmLib.realm_object_to_string(pointer).cast().toRealmDartString(freeRealmMemory: true)!; + } + + void delete() { + invokeGetBool(() => realmLib.realm_object_delete(pointer)); + } } diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 87c06be80..033996d2c 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -53,6 +53,7 @@ part 'realm_handle.dart'; part 'results_handle.dart'; part 'rooted_handle.dart'; part 'schema_handle.dart'; +part 'session_handle.dart'; part 'subscription_handle.dart'; part 'subscription_set_handle.dart'; part 'user_handle.dart'; @@ -615,18 +616,12 @@ class _RealmCore { () => realmLib.realm_set_dictionary(object.handle.pointer, propertyKey)); } - String objectToString(RealmObjectBase object) { - return realmLib.realm_object_to_string(object.handle.pointer).cast().toRealmDartString(freeRealmMemory: true)!; - } + String objectToString(RealmObjectBase object) => object.handle.objectToString(); // For debugging // ignore: unused_element int get _threadId => realmLib.realm_dart_get_thread_id(); - void deleteRealmObject(RealmObjectBase object) { - invokeGetBool(() => realmLib.realm_object_delete(object.handle.pointer)); - } - ResultsHandle queryList(RealmList target, String query, List args) { return using((arena) { final length = args.length; @@ -1420,46 +1415,6 @@ class _RealmCore { return AuthProviderTypeInternal.getByValue(provider); } - String sessionGetPath(Session session) { - return realmLib.realm_sync_session_get_file_path(session.handle.pointer).cast().toRealmDartString()!; - } - - SessionState sessionGetState(Session session) { - final value = realmLib.realm_sync_session_get_state(session.handle.pointer); - return _convertCoreSessionState(value); - } - - ConnectionState sessionGetConnectionState(Session session) { - final value = realmLib.realm_sync_session_get_connection_state(session.handle.pointer); - return ConnectionState.values[value]; - } - - UserHandle sessionGetUser(Session session) { - return UserHandle._(realmLib.realm_sync_session_get_user(session.handle.pointer)); - } - - SessionState _convertCoreSessionState(int value) { - switch (value) { - case 0: // RLM_SYNC_SESSION_STATE_ACTIVE - case 1: // RLM_SYNC_SESSION_STATE_DYING - return SessionState.active; - case 2: // RLM_SYNC_SESSION_STATE_INACTIVE - case 3: // RLM_SYNC_SESSION_STATE_WAITING_FOR_ACCESS_TOKEN - case 4: // RLM_SYNC_SESSION_STATE_PAUSED - return SessionState.inactive; - default: - throw Exception("Unexpected SessionState: $value"); - } - } - - void sessionPause(Session session) { - realmLib.realm_sync_session_pause(session.handle.pointer); - } - - void sessionResume(Session session) { - realmLib.realm_sync_session_resume(session.handle.pointer); - } - RealmSyncSessionConnectionStateNotificationTokenHandle sessionRegisterProgressNotifier( Session session, ProgressDirection direction, ProgressMode mode, SessionProgressNotificationsController controller) { final isStreaming = mode == ProgressMode.reportIndefinitely; @@ -1499,41 +1454,6 @@ class _RealmCore { controller.onConnectionStateChange(ConnectionState.values[oldState], ConnectionState.values[newState]); } - Future sessionWaitForUpload(Session session, [CancellationToken? cancellationToken]) { - final completer = CancellableCompleter(cancellationToken); - if (!completer.isCancelled) { - final callback = Pointer.fromFunction)>(_sessionWaitCompletionCallback); - final userdata = realmLib.realm_dart_userdata_async_new(completer, callback.cast(), scheduler.handle.pointer); - realmLib.realm_sync_session_wait_for_upload_completion(session.handle.pointer, realmLib.addresses.realm_dart_sync_wait_for_completion_callback, - userdata.cast(), realmLib.addresses.realm_dart_userdata_async_free); - } - return completer.future; - } - - Future sessionWaitForDownload(Session session, [CancellationToken? cancellationToken]) { - final completer = CancellableCompleter(cancellationToken); - if (!completer.isCancelled) { - final callback = Pointer.fromFunction)>(_sessionWaitCompletionCallback); - final userdata = realmLib.realm_dart_userdata_async_new(completer, callback.cast(), scheduler.handle.pointer); - realmLib.realm_sync_session_wait_for_download_completion(session.handle.pointer, realmLib.addresses.realm_dart_sync_wait_for_completion_callback, - userdata.cast(), realmLib.addresses.realm_dart_userdata_async_free); - } - return completer.future; - } - - static void _sessionWaitCompletionCallback(Object userdata, Pointer errorCode) { - final completer = userdata as CancellableCompleter; - if (completer.isCancelled) { - return; - } - if (errorCode != nullptr) { - // Throw RealmException instead of RealmError to be recoverable by the user. - completer.completeError(RealmException(errorCode.toDart().toString())); - } else { - completer.complete(); - } - } - String _getAppDirectoryFromPlugin() { assert(isFlutterPlatform); @@ -1870,13 +1790,6 @@ class RealmAsyncOpenTaskProgressNotificationTokenHandle extends HandleBase pointer) : super(pointer, 40); } -class SessionHandle extends RootedHandleBase { - @override - bool get shouldRoot => true; - - SessionHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 24); -} - extension on List { Pointer toCharPtr(Allocator allocator) { return toUint8Ptr(allocator).cast(); diff --git a/packages/realm_dart/lib/src/native/scheduler_handle.dart b/packages/realm_dart/lib/src/native/scheduler_handle.dart index 881e18c1d..51d396788 100644 --- a/packages/realm_dart/lib/src/native/scheduler_handle.dart +++ b/packages/realm_dart/lib/src/native/scheduler_handle.dart @@ -1,6 +1,12 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 +import 'dart:ffi'; + +import 'handle_base.dart'; +import 'realm_bindings.dart'; +import 'realm_library.dart'; + class SchedulerHandle extends HandleBase { SchedulerHandle._(Pointer pointer) : super(pointer, 24); diff --git a/packages/realm_dart/lib/src/native/session_handle.dart b/packages/realm_dart/lib/src/native/session_handle.dart new file mode 100644 index 000000000..1fe02afcd --- /dev/null +++ b/packages/realm_dart/lib/src/native/session_handle.dart @@ -0,0 +1,94 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + +part of 'realm_core.dart'; + +class SessionHandle extends RootedHandleBase { + @override + bool get shouldRoot => true; + + SessionHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 24); + + String get path { + return realmLib.realm_sync_session_get_file_path(pointer).cast().toRealmDartString()!; + } + + ConnectionState get connectionState { + final value = realmLib.realm_sync_session_get_connection_state(pointer); + return ConnectionState.values[value]; + } + + UserHandle get user { + return UserHandle._(realmLib.realm_sync_session_get_user(pointer)); + } + + SessionState get state { + final value = realmLib.realm_sync_session_get_state(pointer); + return _convertCoreSessionState(value); + } + + SessionState _convertCoreSessionState(int value) { + switch (value) { + case 0: // RLM_SYNC_SESSION_STATE_ACTIVE + case 1: // RLM_SYNC_SESSION_STATE_DYING + return SessionState.active; + case 2: // RLM_SYNC_SESSION_STATE_INACTIVE + case 3: // RLM_SYNC_SESSION_STATE_WAITING_FOR_ACCESS_TOKEN + case 4: // RLM_SYNC_SESSION_STATE_PAUSED + return SessionState.inactive; + default: + throw Exception("Unexpected SessionState: $value"); + } + } + + void pause() { + realmLib.realm_sync_session_pause(pointer); + } + + void resume() { + realmLib.realm_sync_session_resume(pointer); + } + + Future waitForUpload([CancellationToken? cancellationToken]) { + final completer = CancellableCompleter(cancellationToken); + if (!completer.isCancelled) { + final callback = Pointer.fromFunction)>(_waitCompletionCallback); + final userdata = realmLib.realm_dart_userdata_async_new(completer, callback.cast(), scheduler.handle.pointer); + realmLib.realm_sync_session_wait_for_upload_completion( + pointer, + realmLib.addresses.realm_dart_sync_wait_for_completion_callback, + userdata.cast(), + realmLib.addresses.realm_dart_userdata_async_free, + ); + } + return completer.future; + } + + Future waitForDownload([CancellationToken? cancellationToken]) { + final completer = CancellableCompleter(cancellationToken); + if (!completer.isCancelled) { + final callback = Pointer.fromFunction)>(_waitCompletionCallback); + final userdata = realmLib.realm_dart_userdata_async_new(completer, callback.cast(), scheduler.handle.pointer); + realmLib.realm_sync_session_wait_for_download_completion( + pointer, + realmLib.addresses.realm_dart_sync_wait_for_completion_callback, + userdata.cast(), + realmLib.addresses.realm_dart_userdata_async_free, + ); + } + return completer.future; + } + + static void _waitCompletionCallback(Object userdata, Pointer errorCode) { + final completer = userdata as CancellableCompleter; + if (completer.isCancelled) { + return; + } + if (errorCode != nullptr) { + // Throw RealmException instead of RealmError to be recoverable by the user. + completer.completeError(RealmException(errorCode.toDart().toString())); + } else { + completer.complete(); + } + } +} diff --git a/packages/realm_dart/lib/src/realm_class.dart b/packages/realm_dart/lib/src/realm_class.dart index c13226178..0526295d9 100644 --- a/packages/realm_dart/lib/src/realm_class.dart +++ b/packages/realm_dart/lib/src/realm_class.dart @@ -317,7 +317,7 @@ class Realm implements Finalizable { _ensureManagedByThis(object, 'delete object from Realm'); - realmCore.deleteRealmObject(object); + object.handle.delete(); } /// Deletes many [RealmObject]s from this `Realm`. diff --git a/packages/realm_dart/lib/src/session.dart b/packages/realm_dart/lib/src/session.dart index 8d1ade90b..e691887a8 100644 --- a/packages/realm_dart/lib/src/session.dart +++ b/packages/realm_dart/lib/src/session.dart @@ -18,38 +18,38 @@ class Session implements Finalizable { final SessionHandle _handle; /// The on-disk path of the file backing the [Realm] this [Session] represents - String get realmPath => realmCore.sessionGetPath(this); + String get realmPath => this.handle.path; /// The session’s current state. This is different from [connectionState] since a /// session may be active, even if the connection is disconnected (e.g. due to the device /// being offline). - SessionState get state => realmCore.sessionGetState(this); + SessionState get state => this.handle.state; /// The session’s current connection state. This is the physical state of the connection /// and is different from the session's logical state, which is returned by [state]. - ConnectionState get connectionState => realmCore.sessionGetConnectionState(this); + ConnectionState get connectionState => this.handle.connectionState; /// The [User] that owns the [Realm] this [Session] is synchronizing. - User get user => UserInternal.create(realmCore.sessionGetUser(this)); + User get user => UserInternal.create(this.handle.user); Session._(this._handle); /// Pauses any synchronization with the server until the Realm is re-opened again /// after fully closing it or [resume] is called. - void pause() => realmCore.sessionPause(this); + void pause() => this.handle.pause(); /// Attempts to resume the session and enable synchronization with the server. /// All sessions are active by default and calling this method is only necessary /// if [pause] was called previously. - void resume() => realmCore.sessionResume(this); + void resume() => this.handle.resume(); /// Waits for the [Session] to finish all pending uploads. /// An optional [cancellationToken] can be used to cancel the wait operation. - Future waitForUpload([CancellationToken? cancellationToken]) => realmCore.sessionWaitForUpload(this, cancellationToken); + Future waitForUpload([CancellationToken? cancellationToken]) => this.handle.waitForUpload(cancellationToken); /// Waits for the [Session] to finish all pending downloads. /// An optional [cancellationToken] can be used to cancel the wait operation. - Future waitForDownload([CancellationToken? cancellationToken]) => realmCore.sessionWaitForDownload(this, cancellationToken); + Future waitForDownload([CancellationToken? cancellationToken]) => this.handle.waitForDownload(cancellationToken); /// Gets a [Stream] of [SyncProgress] that can be used to track upload or download progress. Stream getProgressStream(ProgressDirection direction, ProgressMode mode) { From ff70878d6fb578128462fada6a96fff1bf79bd15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Sun, 14 Apr 2024 13:45:19 +0200 Subject: [PATCH 30/68] UserHandle.linkCredentials/.createApiKey/.fetchApiKey/.fetchAllApiKeys.deleteApiKey/.disableApiKey/.enableApiKey --- .../realm_dart/lib/src/native/app_handle.dart | 16 --- .../realm_dart/lib/src/native/realm_core.dart | 101 --------------- .../lib/src/native/user_handle.dart | 122 +++++++++++++++++- packages/realm_dart/lib/src/user.dart | 14 +- 4 files changed, 127 insertions(+), 126 deletions(-) diff --git a/packages/realm_dart/lib/src/native/app_handle.dart b/packages/realm_dart/lib/src/native/app_handle.dart index 432020bd0..e8a624591 100644 --- a/packages/realm_dart/lib/src/native/app_handle.dart +++ b/packages/realm_dart/lib/src/native/app_handle.dart @@ -113,22 +113,6 @@ class AppHandle extends HandleBase { return completer.future; } - Future linkCredentials(UserHandle user, RealmAppCredentialsHandle credentials) { - final completer = Completer(); - invokeGetBool( - () => realmLib.realm_app_link_user( - pointer, - user.pointer, - credentials.pointer, - realmLib.addresses.realm_dart_user_completion_callback, - _createAsyncUserCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ), - "Link credentials failed", - ); - return completer.future; - } - String get id { return realmLib.realm_app_get_app_id(pointer).cast().toRealmDartString()!; } diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 033996d2c..f7bfa16c9 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -1529,107 +1529,6 @@ class _RealmCore { }); } - Future createApiKey(User user, String name) { - return using((Arena arena) { - final namePtr = name.toCharPtr(arena); - final completer = Completer(); - invokeGetBool(() => realmLib.realm_app_user_apikey_provider_client_create_apikey( - user.app.handle.pointer, - user.handle.pointer, - namePtr, - realmLib.addresses.realm_dart_apikey_callback, - _createAsyncApikeyCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - )); - - return completer.future; - }); - } - - Future fetchApiKey(User user, ObjectId id) { - return using((Arena arena) { - final completer = Completer(); - final native_id = id.toNative(arena); - invokeGetBool(() => realmLib.realm_app_user_apikey_provider_client_fetch_apikey( - user.app.handle.pointer, - user.handle.pointer, - native_id.ref, - realmLib.addresses.realm_dart_apikey_callback, - _createAsyncApikeyCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - )); - - return completer.future; - }); - } - - Future> fetchAllApiKeys(User user) { - return using((Arena arena) { - final completer = Completer>(); - invokeGetBool(() => realmLib.realm_app_user_apikey_provider_client_fetch_apikeys( - user.app.handle.pointer, - user.handle.pointer, - realmLib.addresses.realm_dart_apikey_list_callback, - _createAsyncApikeyListCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - )); - - return completer.future; - }); - } - - Future deleteApiKey(User user, ObjectId id) { - return using((Arena arena) { - final completer = Completer(); - final native_id = id.toNative(arena); - invokeGetBool(() => realmLib.realm_app_user_apikey_provider_client_delete_apikey( - user.app.handle.pointer, - user.handle.pointer, - native_id.ref, - realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - )); - - return completer.future; - }); - } - - Future disableApiKey(User user, ObjectId objectId) { - return using((Arena arena) { - final completer = Completer(); - final native_id = objectId.toNative(arena); - - invokeGetBool(() => realmLib.realm_app_user_apikey_provider_client_disable_apikey( - user.app.handle.pointer, - user.handle.pointer, - native_id.ref, - realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - )); - - return completer.future; - }); - } - - Future enableApiKey(User user, ObjectId objectId) { - return using((Arena arena) { - final completer = Completer(); - final native_id = objectId.toNative(arena); - invokeGetBool(() => realmLib.realm_app_user_apikey_provider_client_enable_apikey( - user.app.handle.pointer, - user.handle.pointer, - native_id.ref, - realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - )); - - return completer.future; - }); - } - static void _call_app_function_callback(Pointer userdata, Pointer response, Pointer error) { final Completer completer = userdata.toObject(); diff --git a/packages/realm_dart/lib/src/native/user_handle.dart b/packages/realm_dart/lib/src/native/user_handle.dart index bb0993b23..9e91d5e48 100644 --- a/packages/realm_dart/lib/src/native/user_handle.dart +++ b/packages/realm_dart/lib/src/native/user_handle.dart @@ -50,9 +50,8 @@ class UserHandle extends HandleBase { return result; } - Future logOut() { + Future logOut() async { invokeGetBool(() => realmLib.realm_user_log_out(pointer), "Logout failed"); - return Future.value(); // why?! } String? get deviceId { @@ -90,4 +89,123 @@ class UserHandle extends HandleBase { final customDataPtr = realmLib.realm_user_get_custom_data(pointer); return customDataPtr.cast().toRealmDartString(freeRealmMemory: true, treatEmptyAsNull: true); } + + Future linkCredentials(AppHandle app, RealmAppCredentialsHandle credentials) { + final completer = Completer(); + invokeGetBool( + () => realmLib.realm_app_link_user( + app.pointer, + pointer, + credentials.pointer, + realmLib.addresses.realm_dart_user_completion_callback, + _createAsyncUserCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ), + "Link credentials failed", + ); + return completer.future; + } + + Future createApiKey(AppHandle app, String name) { + return using((Arena arena) { + final namePtr = name.toCharPtr(arena); + final completer = Completer(); + invokeGetBool( + () => realmLib.realm_app_user_apikey_provider_client_create_apikey( + app.pointer, + pointer, + namePtr, + realmLib.addresses.realm_dart_apikey_callback, + _createAsyncApikeyCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ), + ); + + return completer.future; + }); + } + + Future fetchApiKey(AppHandle app, ObjectId id) { + return using((Arena arena) { + final completer = Completer(); + final nativeId = id.toNative(arena); + invokeGetBool(() => realmLib.realm_app_user_apikey_provider_client_fetch_apikey( + app.pointer, + pointer, + nativeId.ref, + realmLib.addresses.realm_dart_apikey_callback, + _createAsyncApikeyCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + )); + + return completer.future; + }); + } + + Future> fetchAllApiKeys(AppHandle app) { + return using((Arena arena) { + final completer = Completer>(); + invokeGetBool(() => realmLib.realm_app_user_apikey_provider_client_fetch_apikeys( + app.pointer, + pointer, + realmLib.addresses.realm_dart_apikey_list_callback, + _createAsyncApikeyListCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + )); + + return completer.future; + }); + } + + Future deleteApiKey(AppHandle app, ObjectId id) { + return using((Arena arena) { + final completer = Completer(); + final nativeId = id.toNative(arena); + invokeGetBool(() => realmLib.realm_app_user_apikey_provider_client_delete_apikey( + app.pointer, + pointer, + nativeId.ref, + realmLib.addresses.realm_dart_void_completion_callback, + _createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + )); + + return completer.future; + }); + } + + Future disableApiKey(AppHandle app, ObjectId objectId) { + return using((Arena arena) { + final completer = Completer(); + final nativeId = objectId.toNative(arena); + + invokeGetBool(() => realmLib.realm_app_user_apikey_provider_client_disable_apikey( + app.pointer, + pointer, + nativeId.ref, + realmLib.addresses.realm_dart_void_completion_callback, + _createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + )); + + return completer.future; + }); + } + + Future enableApiKey(AppHandle app, ObjectId objectId) { + return using((Arena arena) { + final completer = Completer(); + final nativeId = objectId.toNative(arena); + invokeGetBool(() => realmLib.realm_app_user_apikey_provider_client_enable_apikey( + app.pointer, + pointer, + nativeId.ref, + realmLib.addresses.realm_dart_void_completion_callback, + _createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + )); + + return completer.future; + }); + } } diff --git a/packages/realm_dart/lib/src/user.dart b/packages/realm_dart/lib/src/user.dart index a84809dd7..bcdfa8148 100644 --- a/packages/realm_dart/lib/src/user.dart +++ b/packages/realm_dart/lib/src/user.dart @@ -136,7 +136,7 @@ class User { /// await user.linkCredentials(Credentials.emailPassword("username", "password")); /// ``` Future linkCredentials(Credentials credentials) async { - final userHandle = await app.handle.linkCredentials(handle, credentials.handle); + final userHandle = await handle.linkCredentials(app.handle, credentials.handle); return UserInternal.create(userHandle, app); } @@ -276,42 +276,42 @@ class ApiKeyClient { Future create(String name) async { _user._ensureLoggedIn('create an API key'); - return realmCore.createApiKey(_user, name); + return _user.handle.createApiKey(_user.app.handle, name); } /// Fetches a specific API key by id. Future fetch(ObjectId id) { _user._ensureLoggedIn('fetch an API key'); - return realmCore.fetchApiKey(_user, id).handle404(); + return _user.handle.fetchApiKey(_user.app.handle, id).handle404(); } /// Fetches all API keys associated with the user. Future> fetchAll() async { _user._ensureLoggedIn('fetch all API keys'); - return realmCore.fetchAllApiKeys(_user); + return _user.handle.fetchAllApiKeys(_user.app.handle); } /// Deletes a specific API key by id. Future delete(ObjectId objectId) { _user._ensureLoggedIn('delete an API key'); - return realmCore.deleteApiKey(_user, objectId).handle404(); + return _user.handle.deleteApiKey(_user.app.handle, objectId).handle404(); } /// Disables an API key by id. Future disable(ObjectId objectId) { _user._ensureLoggedIn('disable an API key'); - return realmCore.disableApiKey(_user, objectId).handle404(id: objectId); + return _user.handle.disableApiKey(_user.app.handle, objectId).handle404(id: objectId); } /// Enables an API key by id. Future enable(ObjectId objectId) { _user._ensureLoggedIn('enable an API key'); - return realmCore.enableApiKey(_user, objectId).handle404(id: objectId); + return _user.handle.enableApiKey(_user.app.handle, objectId).handle404(id: objectId); } } From 72c42f2e5e4955b2949b59fa9c47b03410570437 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Mon, 15 Apr 2024 09:51:53 +0200 Subject: [PATCH 31/68] Refactor RealmListHandle (now ListHandle) --- packages/realm_dart/lib/src/app.dart | 2 +- packages/realm_dart/lib/src/list.dart | 34 +- .../lib/src/native/list_handle.dart | 123 ++++++ .../realm_dart/lib/src/native/realm_core.dart | 374 ++++++------------ packages/realm_dart/lib/src/realm_class.dart | 4 +- packages/realm_dart/lib/src/realm_object.dart | 2 +- packages/realm_dart/lib/src/session.dart | 16 +- packages/realm_dart/test/realm_test.dart | 4 +- 8 files changed, 281 insertions(+), 278 deletions(-) create mode 100644 packages/realm_dart/lib/src/native/list_handle.dart diff --git a/packages/realm_dart/lib/src/app.dart b/packages/realm_dart/lib/src/app.dart index 9a7d066d6..0c5fb25c0 100644 --- a/packages/realm_dart/lib/src/app.dart +++ b/packages/realm_dart/lib/src/app.dart @@ -144,7 +144,7 @@ class App implements Finalizable { /// The id of this application. This is the same as the appId in the [AppConfiguration] used to /// create this [App]. - String get id => this.handle.id; + String get id => handle.id; /// Create an app with a particular [AppConfiguration]. This constructor should only be used on the main isolate and, /// ideally, only once as soon as the app starts. diff --git a/packages/realm_dart/lib/src/list.dart b/packages/realm_dart/lib/src/list.dart index 313fae091..7fdf2c0f4 100644 --- a/packages/realm_dart/lib/src/list.dart +++ b/packages/realm_dart/lib/src/list.dart @@ -32,7 +32,7 @@ abstract class RealmList with RealmEntity implements List, /// Converts this [List] to a [RealmResults]. RealmResults asResults(); - factory RealmList._(RealmListHandle handle, Realm realm, RealmObjectMetadata? metadata) => ManagedRealmList._(handle, realm, metadata); + factory RealmList._(ListHandle handle, Realm realm, RealmObjectMetadata? metadata) => ManagedRealmList._(handle, realm, metadata); /// Creates an unmanaged RealmList from [items] factory RealmList(Iterable items) => UnmanagedRealmList(items); @@ -45,7 +45,7 @@ abstract class RealmList with RealmEntity implements List, } class ManagedRealmList with RealmEntity, ListMixin implements RealmList { - final RealmListHandle _handle; + final ListHandle _handle; @override late final RealmObjectMetadata? _metadata; @@ -55,7 +55,7 @@ class ManagedRealmList with RealmEntity, ListMixin impleme } @override - int get length => realmCore.getListSize(handle); + int get length => handle.size; /// Setting the `length` is a required method on [List], but makes less sense /// for [RealmList]s. You can only decrease the length, increasing it doesn't @@ -100,7 +100,7 @@ class ManagedRealmList with RealmEntity, ListMixin impleme } try { - var value = realmCore.listGetElementAt(this, index); + var value = handle.elementAt(realm, index); if (value is ObjectHandle) { late RealmObjectMetadata targetMetadata; late Type type; @@ -141,19 +141,19 @@ class ManagedRealmList with RealmEntity, ListMixin impleme @override T removeAt(int index) { final result = this[index]; - realmCore.listRemoveElementAt(handle, index); + handle.removeAt(index); return result; } /// Move the element at index [from] to index [to]. void move(int from, int to) { - realmCore.listMoveElement(handle, from, to); + handle.move(from, to); } /// Removes all objects from this list; the length of the list becomes zero. /// The objects are not deleted from the realm, but are no longer referenced from this list. @override - void clear() => realmCore.listClear(handle); + void clear() => handle.clear(); @override int indexOf(covariant T element, [int start = 0]) { @@ -172,12 +172,12 @@ class ManagedRealmList with RealmEntity, ListMixin impleme } if (start < 0) start = 0; - final index = realmCore.listFind(this, element); + final index = handle.indexOf(element); return index < start ? -1 : index; // to align with dart list semantics } @override - bool get isValid => realmCore.listIsValid(this); + bool get isValid => this.handle.isValid; @override RealmList freeze() { @@ -190,7 +190,7 @@ class ManagedRealmList with RealmEntity, ListMixin impleme } @override - RealmResults asResults() => RealmResultsInternal.create(realmCore.resultsFromList(this), realm, metadata); + RealmResults asResults() => RealmResultsInternal.create(handle.asResults(), realm, metadata); @override Stream> get changes { @@ -263,7 +263,7 @@ extension RealmListInternal on RealmList { ManagedRealmList asManaged() => this is ManagedRealmList ? this as ManagedRealmList : throw RealmStateError('$this is not managed'); - RealmListHandle get handle { + ListHandle get handle { final result = asManaged()._handle; if (result.released) { throw RealmClosedError('Cannot access a list that belongs to a closed Realm'); @@ -278,14 +278,14 @@ extension RealmListInternal on RealmList { return UnmanagedRealmList._(items); } - static RealmList create(RealmListHandle handle, Realm realm, RealmObjectMetadata? metadata) => RealmList._(handle, realm, metadata); + static RealmList create(ListHandle handle, Realm realm, RealmObjectMetadata? metadata) => RealmList._(handle, realm, metadata); - static void setValue(RealmListHandle handle, Realm realm, int index, Object? value, {bool update = false, bool insert = false}) { + static void setValue(ListHandle handle, Realm realm, int index, Object? value, {bool update = false, bool insert = false}) { if (index < 0) { throw RealmException("Index can not be negative: $index"); } - final length = realmCore.getListSize(handle); + final length = handle.size; if (index > length) { throw RealmException('Index can not exceed the size of the list: $index, size: $length'); } @@ -297,19 +297,19 @@ extension RealmListInternal on RealmList { } final objHandle = - insert || index >= length ? realmCore.listInsertEmbeddedObjectAt(realm, handle, index) : realmCore.listSetEmbeddedObjectAt(realm, handle, index); + insert || index >= length ? handle.insertEmbeddedAt(index) : handle.setEmbeddedAt(index); realm.manageEmbedded(objHandle, value); return; } if (value is RealmValue && value.type.isCollection) { - realmCore.listAddCollectionAt(handle, realm, index, value, insert || index >= length); + handle.addOrUpdateCollectionAt(realm, index, value, insert || index >= length); return; } realm.addUnmanagedRealmObjectFromValue(value, update); - realmCore.listAddElementAt(handle, index, value, insert || index >= length); + handle.addOrUpdateAt(index, value, insert || index >= length); } on Exception catch (e) { throw RealmException("Error setting value at index $index. Error: $e"); } diff --git a/packages/realm_dart/lib/src/native/list_handle.dart b/packages/realm_dart/lib/src/native/list_handle.dart new file mode 100644 index 000000000..e83c1e59d --- /dev/null +++ b/packages/realm_dart/lib/src/native/list_handle.dart @@ -0,0 +1,123 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + +part of 'realm_core.dart'; + +class ListHandle extends CollectionHandleBase { + ListHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 88); + + bool get isValid => realmLib.realm_list_is_valid(pointer); + + ResultsHandle asResults() { + final ptr = invokeGetPointer(() => realmLib.realm_list_to_results(pointer)); + return ResultsHandle._(ptr, _root); + } + + int get size { + return using((Arena arena) { + final size = arena(); + invokeGetBool(() => realmLib.realm_list_size(pointer, size)); + return size.value; + }); + } + + void removeAt(int index) { + invokeGetBool(() => realmLib.realm_list_erase(pointer, index)); + } + + void move(int from, int to) { + invokeGetBool(() => realmLib.realm_list_move(pointer, from, to)); + } + + void deleteAll() { + invokeGetBool(() => realmLib.realm_list_remove_all(pointer)); + } + + int indexOf(Object? value) { + return using((Arena arena) { + final outIndex = arena(); + final outFound = arena(); + + // TODO: how should this behave for collections + final realmValue = _toRealmValue(value, arena); + invokeGetBool( + () => realmLib.realm_list_find( + pointer, + realmValue, + outIndex, + outFound, + ), + ); + return outFound.value ? outIndex.value : -1; + }); + } + + void clear() { + invokeGetBool(() => realmLib.realm_list_clear(pointer)); + } + + // TODO: avoid taking the [realm] parameter + Object? elementAt(Realm realm, int index) { + return using((Arena arena) { + final realmValue = arena(); + invokeGetBool(() => realmLib.realm_list_get(pointer, index, realmValue)); + return realmValue.toDartValue(realm, () => realmLib.realm_list_get_list(pointer, index), () => realmLib.realm_list_get_dictionary(pointer, index)); + }); + } + + // TODO: Consider splitting into two methods + void addOrUpdateAt(int index, Object? value, bool insert) { + using((Arena arena) { + final realmValue = _toRealmValue(value, arena); + invokeGetBool(() => (insert ? realmLib.realm_list_insert : realmLib.realm_list_set)(pointer, index, realmValue.ref)); + }); + } + + // TODO: avoid taking the [realm] parameter + void addOrUpdateCollectionAt(Realm realm, int index, RealmValue value, bool insert) { + _createCollection(realm, value, () => (insert ? realmLib.realm_list_insert_list : realmLib.realm_list_set_list)(pointer, index), + () => (insert ? realmLib.realm_list_insert_dictionary : realmLib.realm_list_set_dictionary)(pointer, index)); + } + + ObjectHandle setEmbeddedAt(int index) { + final ptr = invokeGetPointer(() => realmLib.realm_list_set_embedded(pointer, index)); + return ObjectHandle._(ptr, _root); + } + + ObjectHandle insertEmbeddedAt(int index) { + final ptr = invokeGetPointer(() => realmLib.realm_list_insert_embedded(pointer, index)); + return ObjectHandle._(ptr, _root); + } + + ResultsHandle query(String query, List args) { + return using((arena) { + final length = args.length; + final argsPointer = arena(length); + for (var i = 0; i < length; ++i) { + _intoRealmQueryArg(args[i], argsPointer + i, arena); + } + final queryHandle = QueryHandle._( + invokeGetPointer( + () => realmLib.realm_query_parse_for_list( + pointer, + query.toCharPtr(arena), + length, + argsPointer, + ), + ), + _root); + return queryHandle.findAll(); + }); + } + + RealmNotificationTokenHandle subscribeListNotifications(NotificationsController controller) { + final ptr = invokeGetPointer(() => realmLib.realm_list_add_notification_callback( + pointer, + controller.toPersistentHandle(), + realmLib.addresses.realm_dart_delete_persistent_handle, + nullptr, + Pointer.fromFunction(collection_change_callback), + )); + return RealmNotificationTokenHandle._(ptr, _root); + } +} diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index f7bfa16c9..9473cdd97 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -46,6 +46,7 @@ part 'config_handle.dart'; part 'convert.dart'; part 'decimal128.dart'; part 'error_handling.dart'; +part 'list_handle.dart'; part 'mutable_subscription_set_handle.dart'; part 'object_handle.dart'; part 'query_handle.dart'; @@ -54,6 +55,7 @@ part 'results_handle.dart'; part 'rooted_handle.dart'; part 'schema_handle.dart'; part 'session_handle.dart'; +part 'set_handle.dart'; part 'subscription_handle.dart'; part 'subscription_set_handle.dart'; part 'user_handle.dart'; @@ -351,6 +353,125 @@ Pointer _createAsyncApikeyListCallbackUserdata(Complet return userdata.cast(); } +void _createCollection(Realm realm, RealmValue value, Pointer Function() createList, Pointer Function() createMap) { + CollectionHandleBase? collectionHandle; + try { + switch (value.collectionType) { + case RealmCollectionType.list: + final listPointer = invokeGetPointer(createList); + final listHandle = ListHandle._(listPointer, realm.handle); + collectionHandle = listHandle; + + final list = realm.createList(listHandle, null); + + // Necessary since Core will not clear the collection if the value was already a collection + list.clear(); + + for (final item in value.value as List) { + list.add(item); + } + case RealmCollectionType.map: + final mapPointer = invokeGetPointer(createMap); + final mapHandle = RealmMapHandle._(mapPointer, realm.handle); + collectionHandle = mapHandle; + + final map = realm.createMap(mapHandle, null); + + // Necessary since Core will not clear the collection if the value was already a collection + map.clear(); + + for (final kvp in (value.value as Map).entries) { + map[kvp.key] = kvp.value; + } + default: + throw RealmStateError('_createCollection invoked with type that is not list or map.'); + } + } finally { + collectionHandle?.release(); + } +} + +void collection_change_callback(Pointer userdata, Pointer data) { + final NotificationsController controller = userdata.toObject(); + + if (data == nullptr) { + controller.onError(RealmError("Invalid notifications data received")); + return; + } + + try { + final clonedData = realmLib.realm_clone(data.cast()); + if (clonedData == nullptr) { + controller.onError(RealmError("Error while cloning notifications data")); + return; + } + + final changesHandle = RealmCollectionChangesHandle._(clonedData.cast()); + controller.onChanges(changesHandle); + } catch (e) { + controller.onError(RealmError("Error handling change notifications. Error: $e")); + } +} + +void object_change_callback(Pointer userdata, Pointer data) { + final NotificationsController controller = userdata.toObject(); + + if (data == nullptr) { + controller.onError(RealmError("Invalid notifications data received")); + return; + } + + try { + final clonedData = realmLib.realm_clone(data.cast()); + if (clonedData == nullptr) { + controller.onError(RealmError("Error while cloning notifications data")); + return; + } + + final changesHandle = RealmObjectChangesHandle._(clonedData.cast()); + controller.onChanges(changesHandle); + } catch (e) { + controller.onError(RealmError("Error handling change notifications. Error: $e")); + } +} + +void map_change_callback(Pointer userdata, Pointer data) { + final NotificationsController controller = userdata.toObject(); + + if (data == nullptr) { + controller.onError(RealmError("Invalid notifications data received")); + return; + } + + try { + final clonedData = realmLib.realm_clone(data.cast()); + if (clonedData == nullptr) { + controller.onError(RealmError("Error while cloning notifications data")); + return; + } + + final changesHandle = RealmMapChangesHandle._(clonedData.cast()); + controller.onChanges(changesHandle); + } catch (e) { + controller.onError(RealmError("Error handling change notifications. Error: $e")); + } +} + +void user_change_callback(Object userdata, int data) { + final controller = userdata as UserNotificationsController; + + controller.onUserChanged(); +} + +void schema_change_callback(Pointer userdata, Pointer data) { + final Realm realm = userdata.toObject(); + try { + realm.updateSchema(); + } catch (e) { + Realm.logger.log(LogLevel.error, 'Failed to update Realm schema: $e'); + } +} + // All access to Realm Core functionality goes through this class class _RealmCore { // From realm.h. Currently not exported from the shared library @@ -622,27 +743,6 @@ class _RealmCore { // ignore: unused_element int get _threadId => realmLib.realm_dart_get_thread_id(); - ResultsHandle queryList(RealmList target, String query, List args) { - return using((arena) { - final length = args.length; - final argsPointer = arena(length); - for (var i = 0; i < length; ++i) { - _intoRealmQueryArg(args[i], argsPointer.elementAt(i), arena); - } - final queryHandle = QueryHandle._( - invokeGetPointer( - () => realmLib.realm_query_parse_for_list( - target.handle.pointer, - query.toCharPtr(arena), - length, - argsPointer, - ), - ), - target.realm.handle); - return queryHandle.findAll(); - }); - } - ResultsHandle querySet(RealmSet target, String query, List args) { return using((arena) { final length = args.length; @@ -687,11 +787,6 @@ class _RealmCore { }); } - ResultsHandle resultsFromList(RealmList list) { - final pointer = invokeGetPointer(() => realmLib.realm_list_to_results(list.handle.pointer)); - return ResultsHandle._(pointer, list.realm.handle); - } - ResultsHandle resultsFromSet(RealmSet set) { final pointer = invokeGetPointer(() => realmLib.realm_set_to_results(set.handle.pointer)); return ResultsHandle._(pointer, set.realm.handle); @@ -817,9 +912,9 @@ class _RealmCore { return ObjectHandle._(pointer, realm.handle); } - RealmListHandle getListProperty(RealmObjectBase object, int propertyKey) { + ListHandle getListProperty(RealmObjectBase object, int propertyKey) { final pointer = invokeGetPointer(() => realmLib.realm_get_list(object.handle.pointer, propertyKey)); - return RealmListHandle._(pointer, object.realm.handle); + return ListHandle._(pointer, object.realm.handle); } ResultsHandle getBacklinks(RealmObjectBase object, int sourceTableKey, int propertyKey) { @@ -827,80 +922,6 @@ class _RealmCore { return ResultsHandle._(pointer, object.realm.handle); } - int getListSize(RealmListHandle handle) { - return using((Arena arena) { - final size = arena(); - invokeGetBool(() => realmLib.realm_list_size(handle.pointer, size)); - return size.value; - }); - } - - Object? listGetElementAt(RealmList list, int index) { - return using((Arena arena) { - final realm_value = arena(); - invokeGetBool(() => realmLib.realm_list_get(list.handle.pointer, index, realm_value)); - return realm_value.toDartValue( - list.realm, () => realmLib.realm_list_get_list(list.handle.pointer, index), () => realmLib.realm_list_get_dictionary(list.handle.pointer, index)); - }); - } - - void listAddElementAt(RealmListHandle handle, int index, Object? value, bool insert) { - using((Arena arena) { - final realm_value = _toRealmValue(value, arena); - invokeGetBool(() => (insert ? realmLib.realm_list_insert : realmLib.realm_list_set)(handle.pointer, index, realm_value.ref)); - }); - } - - void listAddCollectionAt(RealmListHandle handle, Realm realm, int index, RealmValue value, bool insert) { - _createCollection(realm, value, () => (insert ? realmLib.realm_list_insert_list : realmLib.realm_list_set_list)(handle.pointer, index), - () => (insert ? realmLib.realm_list_insert_dictionary : realmLib.realm_list_set_dictionary)(handle.pointer, index)); - } - - ObjectHandle listSetEmbeddedObjectAt(Realm realm, RealmListHandle handle, int index) { - final ptr = invokeGetPointer(() => realmLib.realm_list_set_embedded(handle.pointer, index)); - return ObjectHandle._(ptr, realm.handle); - } - - ObjectHandle listInsertEmbeddedObjectAt(Realm realm, RealmListHandle handle, int index) { - final ptr = invokeGetPointer(() => realmLib.realm_list_insert_embedded(handle.pointer, index)); - return ObjectHandle._(ptr, realm.handle); - } - - void listRemoveElementAt(RealmListHandle handle, int index) { - invokeGetBool(() => realmLib.realm_list_erase(handle.pointer, index)); - } - - void listMoveElement(RealmListHandle handle, int from, int to) { - invokeGetBool(() => realmLib.realm_list_move(handle.pointer, from, to)); - } - - void listDeleteAll(RealmList list) { - invokeGetBool(() => realmLib.realm_list_remove_all(list.handle.pointer)); - } - - int listFind(RealmList list, Object? value) { - return using((Arena arena) { - final out_index = arena(); - final out_found = arena(); - - // TODO: how should this behave for collections - final realm_value = _toRealmValue(value, arena); - invokeGetBool( - () => realmLib.realm_list_find( - list.handle.pointer, - realm_value, - out_index, - out_found, - ), - ); - return out_found.value ? out_index.value : -1; - }); - } - - void listClear(RealmListHandle listHandle) { - invokeGetBool(() => realmLib.realm_list_clear(listHandle.pointer)); - } - RealmSetHandle getSetProperty(RealmObjectBase object, int propertyKey) { final pointer = invokeGetPointer(() => realmLib.realm_get_set(object.handle.pointer, propertyKey)); return RealmSetHandle._(pointer, object.realm.handle); @@ -1102,91 +1123,6 @@ class _RealmCore { return realmLib.realm_object_is_valid(object.handle.pointer); } - bool listIsValid(RealmList list) { - return realmLib.realm_list_is_valid(list.handle.pointer); - } - - static void collection_change_callback(Pointer userdata, Pointer data) { - final NotificationsController controller = userdata.toObject(); - - if (data == nullptr) { - controller.onError(RealmError("Invalid notifications data received")); - return; - } - - try { - final clonedData = realmLib.realm_clone(data.cast()); - if (clonedData == nullptr) { - controller.onError(RealmError("Error while cloning notifications data")); - return; - } - - final changesHandle = RealmCollectionChangesHandle._(clonedData.cast()); - controller.onChanges(changesHandle); - } catch (e) { - controller.onError(RealmError("Error handling change notifications. Error: $e")); - } - } - - static void object_change_callback(Pointer userdata, Pointer data) { - final NotificationsController controller = userdata.toObject(); - - if (data == nullptr) { - controller.onError(RealmError("Invalid notifications data received")); - return; - } - - try { - final clonedData = realmLib.realm_clone(data.cast()); - if (clonedData == nullptr) { - controller.onError(RealmError("Error while cloning notifications data")); - return; - } - - final changesHandle = RealmObjectChangesHandle._(clonedData.cast()); - controller.onChanges(changesHandle); - } catch (e) { - controller.onError(RealmError("Error handling change notifications. Error: $e")); - } - } - - static void map_change_callback(Pointer userdata, Pointer data) { - final NotificationsController controller = userdata.toObject(); - - if (data == nullptr) { - controller.onError(RealmError("Invalid notifications data received")); - return; - } - - try { - final clonedData = realmLib.realm_clone(data.cast()); - if (clonedData == nullptr) { - controller.onError(RealmError("Error while cloning notifications data")); - return; - } - - final changesHandle = RealmMapChangesHandle._(clonedData.cast()); - controller.onChanges(changesHandle); - } catch (e) { - controller.onError(RealmError("Error handling change notifications. Error: $e")); - } - } - - static void user_change_callback(Object userdata, int data) { - final controller = userdata as UserNotificationsController; - - controller.onUserChanged(); - } - - static void schema_change_callback(Pointer userdata, Pointer data) { - final Realm realm = userdata.toObject(); - try { - realm.updateSchema(); - } catch (e) { - Realm.logger.log(LogLevel.error, 'Failed to update Realm schema: $e'); - } - } - RealmNotificationTokenHandle subscribeResultsNotifications(RealmResults results, NotificationsController controller) { final pointer = invokeGetPointer(() => realmLib.realm_results_add_notification_callback( results.handle.pointer, @@ -1199,18 +1135,6 @@ class _RealmCore { return RealmNotificationTokenHandle._(pointer, results.realm.handle); } - RealmNotificationTokenHandle subscribeListNotifications(RealmList list, NotificationsController controller) { - final pointer = invokeGetPointer(() => realmLib.realm_list_add_notification_callback( - list.handle.pointer, - controller.toPersistentHandle(), - realmLib.addresses.realm_dart_delete_persistent_handle, - nullptr, - Pointer.fromFunction(collection_change_callback), - )); - - return RealmNotificationTokenHandle._(pointer, list.realm.handle); - } - RealmNotificationTokenHandle subscribeObjectNotifications(RealmObjectBase object, NotificationsController controller, [List? keyPaths]) { return using((Arena arena) { final kpNative = buildAndVerifyKeyPath(object, keyPaths); @@ -1505,11 +1429,11 @@ class _RealmCore { }); } - RealmListHandle? resolveList(ManagedRealmList list, Realm frozenRealm) { + ListHandle? resolveList(ManagedRealmList list, Realm frozenRealm) { return using((Arena arena) { final resultPtr = arena>(); invokeGetBool(() => realmLib.realm_list_resolve_in(list.handle.pointer, frozenRealm.handle.pointer, resultPtr)); - return resultPtr == nullptr ? null : RealmListHandle._(resultPtr.value, frozenRealm.handle); + return resultPtr == nullptr ? null : ListHandle._(resultPtr.value, frozenRealm.handle); }); } @@ -1575,44 +1499,6 @@ class _RealmCore { }); } - void _createCollection(Realm realm, RealmValue value, Pointer Function() createList, Pointer Function() createMap) { - CollectionHandleBase? collectionHandle; - try { - switch (value.collectionType) { - case RealmCollectionType.list: - final listPointer = invokeGetPointer(createList); - final listHandle = RealmListHandle._(listPointer, realm.handle); - collectionHandle = listHandle; - - final list = realm.createList(listHandle, null); - - // Necessary since Core will not clear the collection if the value was already a collection - list.clear(); - - for (final item in value.value as List) { - list.add(item); - } - case RealmCollectionType.map: - final mapPointer = invokeGetPointer(createMap); - final mapHandle = RealmMapHandle._(mapPointer, realm.handle); - collectionHandle = mapHandle; - - final map = realm.createMap(mapHandle, null); - - // Necessary since Core will not clear the collection if the value was already a collection - map.clear(); - - for (final kvp in (value.value as Map).entries) { - map[kvp.key] = kvp.value; - } - default: - throw RealmStateError('_createCollection invoked with type that is not list or map.'); - } - } finally { - collectionHandle?.release(); - } - } - void setLogLevel(LogLevel level, {required LogCategory category}) { using((arena) { realmLib.realm_set_log_level_category(category.toString().toCharPtr(arena), level.index); @@ -1637,14 +1523,6 @@ class _RealmLinkHandle { classKey = link.target_table; } -class RealmListHandle extends CollectionHandleBase { - RealmListHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 88); -} - -class RealmSetHandle extends RootedHandleBase { - RealmSetHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 96); -} - class RealmMapHandle extends CollectionHandleBase { RealmMapHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 96); // TODO: check size } @@ -1885,7 +1763,7 @@ extension on realm_value_t { } final listPointer = invokeGetPointer(() => getList()); - final listHandle = RealmListHandle._(listPointer, realm.handle); + final listHandle = ListHandle._(listPointer, realm.handle); return realm.createList(listHandle, null); case realm_value_type.RLM_TYPE_DICTIONARY: if (getMap == null || realm == null) { diff --git a/packages/realm_dart/lib/src/realm_class.dart b/packages/realm_dart/lib/src/realm_class.dart index 0526295d9..aff6f63fc 100644 --- a/packages/realm_dart/lib/src/realm_class.dart +++ b/packages/realm_dart/lib/src/realm_class.dart @@ -332,7 +332,7 @@ class Realm implements Finalizable { } else if (items is ManagedRealmList) { _ensureManagedByThis(items, 'delete objects from Realm'); - realmCore.listDeleteAll(items); + items.handle.deleteAll(); } else if (items is ManagedRealmSet) { _ensureManagedByThis(items, 'delete objects from Realm'); @@ -744,7 +744,7 @@ extension RealmInternal on Realm { return RealmObjectInternal.create(type, this, handle, accessor); } - RealmList createList(RealmListHandle handle, RealmObjectMetadata? metadata) { + RealmList createList(ListHandle handle, RealmObjectMetadata? metadata) { return RealmListInternal.create(handle, this, metadata); } diff --git a/packages/realm_dart/lib/src/realm_object.dart b/packages/realm_dart/lib/src/realm_object.dart index f9ccc0921..0d66110cf 100644 --- a/packages/realm_dart/lib/src/realm_object.dart +++ b/packages/realm_dart/lib/src/realm_object.dart @@ -271,7 +271,7 @@ class RealmCoreAccessor implements RealmAccessor { if (value is RealmList) { final handle = realmCore.getListProperty(object, propertyMeta.key); if (update) { - realmCore.listClear(handle); + handle.clear(); } for (var i = 0; i < value.length; i++) { diff --git a/packages/realm_dart/lib/src/session.dart b/packages/realm_dart/lib/src/session.dart index e691887a8..ef42609f8 100644 --- a/packages/realm_dart/lib/src/session.dart +++ b/packages/realm_dart/lib/src/session.dart @@ -18,38 +18,38 @@ class Session implements Finalizable { final SessionHandle _handle; /// The on-disk path of the file backing the [Realm] this [Session] represents - String get realmPath => this.handle.path; + String get realmPath => handle.path; /// The session’s current state. This is different from [connectionState] since a /// session may be active, even if the connection is disconnected (e.g. due to the device /// being offline). - SessionState get state => this.handle.state; + SessionState get state => handle.state; /// The session’s current connection state. This is the physical state of the connection /// and is different from the session's logical state, which is returned by [state]. - ConnectionState get connectionState => this.handle.connectionState; + ConnectionState get connectionState => handle.connectionState; /// The [User] that owns the [Realm] this [Session] is synchronizing. - User get user => UserInternal.create(this.handle.user); + User get user => UserInternal.create(handle.user); Session._(this._handle); /// Pauses any synchronization with the server until the Realm is re-opened again /// after fully closing it or [resume] is called. - void pause() => this.handle.pause(); + void pause() => handle.pause(); /// Attempts to resume the session and enable synchronization with the server. /// All sessions are active by default and calling this method is only necessary /// if [pause] was called previously. - void resume() => this.handle.resume(); + void resume() => handle.resume(); /// Waits for the [Session] to finish all pending uploads. /// An optional [cancellationToken] can be used to cancel the wait operation. - Future waitForUpload([CancellationToken? cancellationToken]) => this.handle.waitForUpload(cancellationToken); + Future waitForUpload([CancellationToken? cancellationToken]) => handle.waitForUpload(cancellationToken); /// Waits for the [Session] to finish all pending downloads. /// An optional [cancellationToken] can be used to cancel the wait operation. - Future waitForDownload([CancellationToken? cancellationToken]) => this.handle.waitForDownload(cancellationToken); + Future waitForDownload([CancellationToken? cancellationToken]) => handle.waitForDownload(cancellationToken); /// Gets a [Stream] of [SyncProgress] that can be used to track upload or download progress. Stream getProgressStream(ProgressDirection direction, ProgressMode mode) { diff --git a/packages/realm_dart/test/realm_test.dart b/packages/realm_dart/test/realm_test.dart index befa172e6..74529b469 100644 --- a/packages/realm_dart/test/realm_test.dart +++ b/packages/realm_dart/test/realm_test.dart @@ -392,6 +392,9 @@ void main() { //Ensure the team exists in realm var teams = realm.all(); expect(teams.length, 1); + expect(teams[0].players, newPlayers); + final allPersons = realm.all(); + expect(allPersons.length, 3); //Delete team players realm.write(() => realm.deleteMany(teams[0].players)); @@ -400,7 +403,6 @@ void main() { expect(teams[0].players.length, 0); //Reload all persons from realm and ensure they are deleted - final allPersons = realm.all(); expect(allPersons.length, 0); }); From 1b0b535d02fa49a5a601f1b90c8c81b00fe07926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Mon, 15 Apr 2024 11:58:53 +0200 Subject: [PATCH 32/68] Refactor RealmSetHandle (now SetHandle) --- packages/realm_dart/lib/src/list.dart | 6 +- packages/realm_dart/lib/src/map.dart | 28 +-- .../lib/src/native/list_handle.dart | 2 +- .../realm_dart/lib/src/native/map_handle.dart | 133 +++++++++++ .../realm_dart/lib/src/native/realm_core.dart | 217 ++---------------- .../realm_dart/lib/src/native/set_handle.dart | 110 +++++++++ packages/realm_dart/lib/src/realm_class.dart | 6 +- packages/realm_dart/lib/src/realm_object.dart | 6 +- packages/realm_dart/lib/src/set.dart | 26 +-- 9 files changed, 295 insertions(+), 239 deletions(-) create mode 100644 packages/realm_dart/lib/src/native/map_handle.dart create mode 100644 packages/realm_dart/lib/src/native/set_handle.dart diff --git a/packages/realm_dart/lib/src/list.dart b/packages/realm_dart/lib/src/list.dart index 7fdf2c0f4..01546d245 100644 --- a/packages/realm_dart/lib/src/list.dart +++ b/packages/realm_dart/lib/src/list.dart @@ -177,7 +177,7 @@ class ManagedRealmList with RealmEntity, ListMixin impleme } @override - bool get isValid => this.handle.isValid; + bool get isValid => handle.isValid; @override RealmList freeze() { @@ -245,7 +245,7 @@ extension RealmListOfObject on RealmList { /// /// For more details about the syntax of the Realm Query Language, refer to the documentation: https://www.mongodb.com/docs/realm/realm-query-language/. RealmResults query(String query, [List arguments = const []]) { - final handle = realmCore.queryList(asManaged(), query, arguments); + final handle = asManaged().handle.query(query, arguments); return RealmResultsInternal.create(handle, realm, _metadata); } } @@ -336,7 +336,7 @@ class ListNotificationsController extends NotificationsContro @override RealmNotificationTokenHandle subscribe() { - return realmCore.subscribeListNotifications(list, this); + return list.handle.subscribeForNotifications(this); } Stream> createStream() { diff --git a/packages/realm_dart/lib/src/map.dart b/packages/realm_dart/lib/src/map.dart index 33f5636ec..6e8c91880 100644 --- a/packages/realm_dart/lib/src/map.dart +++ b/packages/realm_dart/lib/src/map.dart @@ -60,7 +60,7 @@ class UnmanagedRealmMap extends collection.DelegatingMap with RealmEntity, MapMixin implements RealmMap { - final RealmMapHandle _handle; + final MapHandle _handle; late final RealmObjectMetadata? _metadata; @@ -69,7 +69,7 @@ class ManagedRealmMap with RealmEntity, MapMixin i } @override - int get length => realmCore.mapGetSize(handle); + int get length => handle.size; @override T? remove(Object? key) { @@ -78,7 +78,7 @@ class ManagedRealmMap with RealmEntity, MapMixin i } final value = this[key]; - if (realmCore.mapRemoveKey(handle, key)) { + if (handle.remove(key)) { return value; } @@ -92,7 +92,7 @@ class ManagedRealmMap with RealmEntity, MapMixin i } try { - var value = realmCore.mapGetElement(this, key); + var value = handle.find(realm, key); if (value is ObjectHandle) { late RealmObjectMetadata targetMetadata; late Type type; @@ -127,10 +127,10 @@ class ManagedRealmMap with RealmEntity, MapMixin i /// Removes all objects from this map; the length of the map becomes zero. /// The objects are not deleted from the realm, but are no longer referenced from this map. @override - void clear() => realmCore.mapClear(handle); + void clear() => handle.clear(); @override - bool get isValid => realmCore.mapIsValid(this); + bool get isValid => handle.isValid; @override RealmMap freeze() { @@ -152,13 +152,13 @@ class ManagedRealmMap with RealmEntity, MapMixin i } @override - Iterable get keys => RealmResultsInternal.create(realmCore.mapGetKeys(this), realm, null); + Iterable get keys => RealmResultsInternal.create(handle.keys, realm, null); @override - Iterable get values => RealmResultsInternal.create(realmCore.mapGetValues(this), realm, metadata); + Iterable get values => RealmResultsInternal.create(handle.values, realm, metadata); @override - bool containsKey(Object? key) => key is String && realmCore.mapContainsKey(this, key); + bool containsKey(Object? key) => key is String && handle.containsKey(key); @override bool containsValue(Object? value) { @@ -180,7 +180,7 @@ class ManagedRealmMap with RealmEntity, MapMixin i } } - return realmCore.mapContainsValue(this, value); + return handle.containsValue(value); } } @@ -239,7 +239,7 @@ extension RealmMapInternal on RealmMap { ManagedRealmMap asManaged() => this is ManagedRealmMap ? this as ManagedRealmMap : throw RealmStateError('$this is not managed'); - RealmMapHandle get handle { + MapHandle get handle { final result = asManaged()._handle; if (result.released) { throw RealmClosedError('Cannot access a map that belongs to a closed Realm'); @@ -252,10 +252,10 @@ extension RealmMapInternal on RealmMap { static RealmMap createFromMap(Map map) => UnmanagedRealmMap._(map); - static RealmMap create(RealmMapHandle handle, Realm realm, RealmObjectMetadata? metadata) => + static RealmMap create(MapHandle handle, Realm realm, RealmObjectMetadata? metadata) => ManagedRealmMap._(handle, realm, metadata); - static void setValue(RealmMapHandle handle, Realm realm, String key, Object? value, {bool update = false}) { + static void setValue(MapHandle handle, Realm realm, String key, Object? value, {bool update = false}) { try { if (value is EmbeddedObject) { if (value.isManaged) { @@ -290,7 +290,7 @@ class MapNotificationsController extends NotificationsControl @override RealmNotificationTokenHandle subscribe() { - return realmCore.subscribeMapNotifications(map, this); + return map.handle.subscribeForNotifications(this); } Stream> createStream() { diff --git a/packages/realm_dart/lib/src/native/list_handle.dart b/packages/realm_dart/lib/src/native/list_handle.dart index e83c1e59d..6d55fe04b 100644 --- a/packages/realm_dart/lib/src/native/list_handle.dart +++ b/packages/realm_dart/lib/src/native/list_handle.dart @@ -110,7 +110,7 @@ class ListHandle extends CollectionHandleBase { }); } - RealmNotificationTokenHandle subscribeListNotifications(NotificationsController controller) { + RealmNotificationTokenHandle subscribeForNotifications(NotificationsController controller) { final ptr = invokeGetPointer(() => realmLib.realm_list_add_notification_callback( pointer, controller.toPersistentHandle(), diff --git a/packages/realm_dart/lib/src/native/map_handle.dart b/packages/realm_dart/lib/src/native/map_handle.dart new file mode 100644 index 000000000..fceadf4ef --- /dev/null +++ b/packages/realm_dart/lib/src/native/map_handle.dart @@ -0,0 +1,133 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + +part of 'realm_core.dart'; + +class MapHandle extends CollectionHandleBase { + MapHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 96); // TODO: check size + + int get size { + return using((Arena arena) { + final outSize = arena(); + invokeGetBool(() => realmLib.realm_dictionary_size(pointer, outSize)); + return outSize.value; + }); + } + + bool remove(String key) { + return using((Arena arena) { + final keyNative = _toRealmValue(key, arena); + final outErased = arena(); + invokeGetBool(() => realmLib.realm_dictionary_erase(pointer, keyNative.ref, outErased)); + return outErased.value; + }); + } + + // TODO: avoid taking the [realm] parameter + Object? find(Realm realm, String key) { + return using((Arena arena) { + final keyNative = _toRealmValue(key, arena); + final outValue = arena(); + final outFound = arena(); + invokeGetBool(() => realmLib.realm_dictionary_find(pointer, keyNative.ref, outValue, outFound)); + if (outFound.value) { + return outValue.toDartValue( + realm, + () => realmLib.realm_dictionary_get_list(pointer, keyNative.ref), + () => realmLib.realm_dictionary_get_dictionary(pointer, keyNative.ref), + ); + } + return null; + }); + } + + bool get isValid { + return realmLib.realm_dictionary_is_valid(pointer); + } + + void clear() { + invokeGetBool(() => realmLib.realm_dictionary_clear(pointer)); + } + + ResultsHandle get keys { + return using((Arena arena) { + final outSize = arena(); + final outKeys = arena>(); + invokeGetBool(() => realmLib.realm_dictionary_get_keys(pointer, outSize, outKeys)); + return ResultsHandle._(outKeys.value, _root); + }); + } + + ResultsHandle get values { + final ptr = invokeGetPointer(() => realmLib.realm_dictionary_to_results(pointer)); + return ResultsHandle._(ptr, _root); + } + + bool containsKey(String key) { + return using((Arena arena) { + final keyNative = _toRealmValue(key, arena); + final found = arena(); + invokeGetBool(() => realmLib.realm_dictionary_contains_key(pointer, keyNative.ref, found)); + return found.value; + }); + } + + int indexOf(Object? value) { + return using((Arena arena) { + // TODO: how should this behave for collections + final valueNative = _toRealmValue(value, arena); + final index = arena(); + invokeGetBool(() => realmLib.realm_dictionary_contains_value(pointer, valueNative.ref, index)); + return index.value; + }); + } + + bool containsValue(Object? value) => indexOf(value) > -1; + + ObjectHandle mapInsertEmbeddedObject(Realm realm, MapHandle handle, String key) { + return using((Arena arena) { + final keyNative = _toRealmValue(key, arena); + final ptr = invokeGetPointer(() => realmLib.realm_dictionary_insert_embedded(handle.pointer, keyNative.ref)); + return ObjectHandle._(ptr, realm.handle); + }); + } + + void mapInsertValue(MapHandle handle, String key, Object? value) { + using((Arena arena) { + final keyNative = _toRealmValue(key, arena); + final valueNative = _toRealmValue(value, arena); + invokeGetBool( + () => realmLib.realm_dictionary_insert( + handle.pointer, + keyNative.ref, + valueNative.ref, + nullptr, + nullptr, + ), + ); + }); + } + + void mapInsertCollection(MapHandle handle, Realm realm, String key, RealmValue value) { + using((Arena arena) { + final keyNative = _toRealmValue(key, arena); + _createCollection( + realm, + value, + () => realmLib.realm_dictionary_insert_list(handle.pointer, keyNative.ref), + () => realmLib.realm_dictionary_insert_dictionary(handle.pointer, keyNative.ref), + ); + }); + } + + RealmNotificationTokenHandle subscribeForNotifications(NotificationsController controller) { + final ptr = invokeGetPointer(() => realmLib.realm_dictionary_add_notification_callback( + pointer, + controller.toPersistentHandle(), + realmLib.addresses.realm_dart_delete_persistent_handle, + nullptr, + Pointer.fromFunction(map_change_callback), + )); + return RealmNotificationTokenHandle._(ptr, _root); + } +} diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 9473cdd97..7b6ac059c 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -47,6 +47,7 @@ part 'convert.dart'; part 'decimal128.dart'; part 'error_handling.dart'; part 'list_handle.dart'; +part 'map_handle.dart'; part 'mutable_subscription_set_handle.dart'; part 'object_handle.dart'; part 'query_handle.dart'; @@ -372,7 +373,7 @@ void _createCollection(Realm realm, RealmValue value, Pointer Functi } case RealmCollectionType.map: final mapPointer = invokeGetPointer(createMap); - final mapHandle = RealmMapHandle._(mapPointer, realm.handle); + final mapHandle = MapHandle._(mapPointer, realm.handle); collectionHandle = mapHandle; final map = realm.createMap(mapHandle, null); @@ -743,27 +744,6 @@ class _RealmCore { // ignore: unused_element int get _threadId => realmLib.realm_dart_get_thread_id(); - ResultsHandle querySet(RealmSet target, String query, List args) { - return using((arena) { - final length = args.length; - final argsPointer = arena(length); - for (var i = 0; i < length; ++i) { - _intoRealmQueryArg(args[i], argsPointer.elementAt(i), arena); - } - final queryHandle = QueryHandle._( - invokeGetPointer( - () => realmLib.realm_query_parse_for_set( - target.handle.pointer, - query.toCharPtr(arena), - length, - argsPointer, - ), - ), - target.realm.handle); - return queryHandle.findAll(); - }); - } - ResultsHandle queryMap(ManagedRealmMap target, String query, List args) { return using((arena) { final length = args.length; @@ -772,7 +752,7 @@ class _RealmCore { _intoRealmQueryArg(args[i], argsPointer.elementAt(i), arena); } - final results = mapGetValues(target); + final results = target.handle.values; final queryHandle = QueryHandle._( invokeGetPointer( () => realmLib.realm_query_parse_for_results( @@ -787,11 +767,6 @@ class _RealmCore { }); } - ResultsHandle resultsFromSet(RealmSet set) { - final pointer = invokeGetPointer(() => realmLib.realm_set_to_results(set.handle.pointer)); - return ResultsHandle._(pointer, set.realm.handle); - } - Object? resultsGetElementAt(RealmResults results, int index) { return using((Arena arena) { final realm_value = arena(); @@ -922,158 +897,12 @@ class _RealmCore { return ResultsHandle._(pointer, object.realm.handle); } - RealmSetHandle getSetProperty(RealmObjectBase object, int propertyKey) { + SetHandle getSetProperty(RealmObjectBase object, int propertyKey) { final pointer = invokeGetPointer(() => realmLib.realm_get_set(object.handle.pointer, propertyKey)); - return RealmSetHandle._(pointer, object.realm.handle); + return SetHandle._(pointer, object.realm.handle); } - bool realmSetInsert(RealmSetHandle handle, Object? value) { - return using((Arena arena) { - final realm_value = _toRealmValue(value, arena); - final out_index = arena(); - final out_inserted = arena(); - invokeGetBool(() => realmLib.realm_set_insert(handle.pointer, realm_value.ref, out_index, out_inserted)); - return out_inserted.value; - }); - } - - Object? realmSetGetElementAt(RealmSet realmSet, int index) { - return using((Arena arena) { - final realm_value = arena(); - invokeGetBool(() => realmLib.realm_set_get(realmSet.handle.pointer, index, realm_value)); - final result = realm_value.toDartValue( - realmSet.realm, () => throw RealmException('Sets cannot contain collections'), () => throw RealmException('Sets cannot contain collections')); - return result; - }); - } - - bool realmSetFind(RealmSet realmSet, Object? value) { - return using((Arena arena) { - // TODO: how should this behave for collections - final realm_value = _toRealmValue(value, arena); - final out_index = arena(); - final out_found = arena(); - invokeGetBool(() => realmLib.realm_set_find(realmSet.handle.pointer, realm_value.ref, out_index, out_found)); - return out_found.value; - }); - } - - bool realmSetErase(RealmSet realmSet, Object? value) { - return using((Arena arena) { - // TODO: do we support sets containing mixed collections - final realm_value = _toRealmValue(value, arena); - final out_erased = arena(); - invokeGetBool(() => realmLib.realm_set_erase(realmSet.handle.pointer, realm_value.ref, out_erased)); - return out_erased.value; - }); - } - - void realmSetClear(RealmSetHandle handle) { - invokeGetBool(() => realmLib.realm_set_clear(handle.pointer)); - } - - int realmSetSize(RealmSet realmSet) { - return using((Arena arena) { - final out_size = arena(); - invokeGetBool(() => realmLib.realm_set_size(realmSet.handle.pointer, out_size)); - return out_size.value; - }); - } - - bool realmSetIsValid(RealmSet realmSet) { - return realmLib.realm_set_is_valid(realmSet.handle.pointer); - } - - void realmSetRemoveAll(RealmSet realmSet) { - invokeGetBool(() => realmLib.realm_set_remove_all(realmSet.handle.pointer)); - } - - RealmNotificationTokenHandle subscribeSetNotifications(RealmSet realmSet, NotificationsController controller) { - final pointer = invokeGetPointer(() => realmLib.realm_set_add_notification_callback( - realmSet.handle.pointer, - controller.toPersistentHandle(), - realmLib.addresses.realm_dart_delete_persistent_handle, - nullptr, - Pointer.fromFunction(collection_change_callback), - )); - - return RealmNotificationTokenHandle._(pointer, realmSet.realm.handle); - } - - int mapGetSize(RealmMapHandle handle) { - return using((Arena arena) { - final size = arena(); - invokeGetBool(() => realmLib.realm_dictionary_size(handle.pointer, size)); - return size.value; - }); - } - - bool mapRemoveKey(RealmMapHandle handle, String key) { - return using((Arena arena) { - final keyValue = _toRealmValue(key, arena); - final out_erased = arena(); - invokeGetBool(() => realmLib.realm_dictionary_erase(handle.pointer, keyValue.ref, out_erased)); - return out_erased.value; - }); - } - - Object? mapGetElement(RealmMap map, String key) { - return using((Arena arena) { - final realm_value = arena(); - final key_value = _toRealmValue(key, arena); - final out_found = arena(); - invokeGetBool(() => realmLib.realm_dictionary_find(map.handle.pointer, key_value.ref, realm_value, out_found)); - if (out_found.value) { - return realm_value.toDartValue(map.realm, () => realmLib.realm_dictionary_get_list(map.handle.pointer, key_value.ref), - () => realmLib.realm_dictionary_get_dictionary(map.handle.pointer, key_value.ref)); - } - - return null; - }); - } - - bool mapIsValid(RealmMap map) { - return realmLib.realm_dictionary_is_valid(map.handle.pointer); - } - - void mapClear(RealmMapHandle mapHandle) { - invokeGetBool(() => realmLib.realm_dictionary_clear(mapHandle.pointer)); - } - - ResultsHandle mapGetKeys(ManagedRealmMap map) { - return using((Arena arena) { - final out_size = arena(); - final out_keys = arena>(); - invokeGetBool(() => realmLib.realm_dictionary_get_keys(map.handle.pointer, out_size, out_keys)); - return ResultsHandle._(out_keys.value, map.realm.handle); - }); - } - - ResultsHandle mapGetValues(ManagedRealmMap map) { - final result = invokeGetPointer(() => realmLib.realm_dictionary_to_results(map.handle.pointer)); - return ResultsHandle._(result, map.realm.handle); - } - - bool mapContainsKey(ManagedRealmMap map, String key) { - return using((Arena arena) { - final key_value = _toRealmValue(key, arena); - final out_found = arena(); - invokeGetBool(() => realmLib.realm_dictionary_contains_key(map.handle.pointer, key_value.ref, out_found)); - return out_found.value; - }); - } - - bool mapContainsValue(ManagedRealmMap map, Object? value) { - return using((Arena arena) { - // TODO: how should this behave for collections - final value_value = _toRealmValue(value, arena); - final out_index = arena(); - invokeGetBool(() => realmLib.realm_dictionary_contains_value(map.handle.pointer, value_value.ref, out_index)); - return out_index.value > -1; - }); - } - - ObjectHandle mapInsertEmbeddedObject(Realm realm, RealmMapHandle handle, String key) { + ObjectHandle mapInsertEmbeddedObject(Realm realm, MapHandle handle, String key) { return using((Arena arena) { final realm_value = _toRealmValue(key, arena); final ptr = invokeGetPointer(() => realmLib.realm_dictionary_insert_embedded(handle.pointer, realm_value.ref)); @@ -1081,7 +910,7 @@ class _RealmCore { }); } - void mapInsertValue(RealmMapHandle handle, String key, Object? value) { + void mapInsertValue(MapHandle handle, String key, Object? value) { using((Arena arena) { final key_value = _toRealmValue(key, arena); final value_value = _toRealmValue(value, arena); @@ -1089,7 +918,7 @@ class _RealmCore { }); } - void mapInsertCollection(RealmMapHandle handle, Realm realm, String key, RealmValue value) { + void mapInsertCollection(MapHandle handle, Realm realm, String key, RealmValue value) { using((Arena arena) { final key_value = _toRealmValue(key, arena); _createCollection(realm, value, () => realmLib.realm_dictionary_insert_list(handle.pointer, key_value.ref), @@ -1097,9 +926,9 @@ class _RealmCore { }); } - RealmMapHandle getMapProperty(RealmObjectBase object, int propertyKey) { + MapHandle getMapProperty(RealmObjectBase object, int propertyKey) { final pointer = invokeGetPointer(() => realmLib.realm_get_dictionary(object.handle.pointer, propertyKey)); - return RealmMapHandle._(pointer, object.realm.handle); + return MapHandle._(pointer, object.realm.handle); } bool _equals(HandleBase first, HandleBase second) { @@ -1168,18 +997,6 @@ class _RealmCore { }); } - RealmNotificationTokenHandle subscribeMapNotifications(RealmMap map, NotificationsController controller) { - final pointer = invokeGetPointer(() => realmLib.realm_dictionary_add_notification_callback( - map.handle.pointer, - controller.toPersistentHandle(), - realmLib.addresses.realm_dart_delete_persistent_handle, - nullptr, - Pointer.fromFunction(map_change_callback), - )); - - return RealmNotificationTokenHandle._(pointer, map.realm.handle); - } - UserNotificationTokenHandle subscribeUserNotifications(UserNotificationsController controller) { final callback = Pointer.fromFunction(user_change_callback); final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); @@ -1437,19 +1254,19 @@ class _RealmCore { }); } - RealmSetHandle? resolveSet(ManagedRealmSet set, Realm frozenRealm) { + SetHandle? resolveSet(ManagedRealmSet set, Realm frozenRealm) { return using((Arena arena) { final resultPtr = arena>(); invokeGetBool(() => realmLib.realm_set_resolve_in(set.handle.pointer, frozenRealm.handle.pointer, resultPtr)); - return resultPtr == nullptr ? null : RealmSetHandle._(resultPtr.value, frozenRealm.handle); + return resultPtr == nullptr ? null : SetHandle._(resultPtr.value, frozenRealm.handle); }); } - RealmMapHandle? resolveMap(ManagedRealmMap map, Realm frozenRealm) { + MapHandle? resolveMap(ManagedRealmMap map, Realm frozenRealm) { return using((Arena arena) { final resultPtr = arena>(); invokeGetBool(() => realmLib.realm_dictionary_resolve_in(map.handle.pointer, frozenRealm.handle.pointer, resultPtr)); - return resultPtr == nullptr ? null : RealmMapHandle._(resultPtr.value, frozenRealm.handle); + return resultPtr == nullptr ? null : MapHandle._(resultPtr.value, frozenRealm.handle); }); } @@ -1523,10 +1340,6 @@ class _RealmLinkHandle { classKey = link.target_table; } -class RealmMapHandle extends CollectionHandleBase { - RealmMapHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 96); // TODO: check size -} - class RealmCallbackTokenHandle extends RootedHandleBase { RealmCallbackTokenHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 32); } @@ -1771,7 +1584,7 @@ extension on realm_value_t { } final mapPointer = invokeGetPointer(() => getMap()); - final mapHandle = RealmMapHandle._(mapPointer, realm.handle); + final mapHandle = MapHandle._(mapPointer, realm.handle); return realm.createMap(mapHandle, null); default: throw RealmException("realm_value_type $type not supported"); diff --git a/packages/realm_dart/lib/src/native/set_handle.dart b/packages/realm_dart/lib/src/native/set_handle.dart new file mode 100644 index 000000000..7a6af0e76 --- /dev/null +++ b/packages/realm_dart/lib/src/native/set_handle.dart @@ -0,0 +1,110 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + +part of 'realm_core.dart'; + +class SetHandle extends RootedHandleBase { + SetHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 96); + + ResultsHandle get asResults { + final ptr = invokeGetPointer(() => realmLib.realm_set_to_results(pointer)); + return ResultsHandle._(ptr, _root); + } + + ResultsHandle query(String query, List args) { + return using((arena) { + final length = args.length; + final argsPointer = arena(length); + for (var i = 0; i < length; ++i) { + _intoRealmQueryArg(args[i], argsPointer + i, arena); + } + final queryHandle = QueryHandle._( + invokeGetPointer( + () => realmLib.realm_query_parse_for_set( + pointer, + query.toCharPtr(arena), + length, + argsPointer, + ), + ), + _root); + return queryHandle.findAll(); + }); + } + + bool insert(Object? value) { + return using((Arena arena) { + final realmValue = _toRealmValue(value, arena); + final outIndex = arena(); + final outInserted = arena(); + invokeGetBool(() => realmLib.realm_set_insert(pointer, realmValue.ref, outIndex, outInserted)); + return outInserted.value; + }); + } + + // TODO: avoid taking the [realm] parameter + Object? elementAt(Realm realm, int index) { + return using((Arena arena) { + final realmValue = arena(); + invokeGetBool(() => realmLib.realm_set_get(pointer, index, realmValue)); + final result = realmValue.toDartValue( + realm, + () => throw RealmException('Sets cannot contain collections'), + () => throw RealmException('Sets cannot contain collections'), + ); + return result; + }); + } + + bool find(Object? value) { + return using((Arena arena) { + // TODO: how should this behave for collections + final realmValue = _toRealmValue(value, arena); + final outIndex = arena(); + final outFound = arena(); + invokeGetBool(() => realmLib.realm_set_find(pointer, realmValue.ref, outIndex, outFound)); + return outFound.value; + }); + } + + bool remove(Object? value) { + return using((Arena arena) { + // TODO: do we support sets containing mixed collections + final realmValue = _toRealmValue(value, arena); + final outErased = arena(); + invokeGetBool(() => realmLib.realm_set_erase(pointer, realmValue.ref, outErased)); + return outErased.value; + }); + } + + void clear() { + invokeGetBool(() => realmLib.realm_set_clear(pointer)); + } + + int get size { + return using((Arena arena) { + final outSize = arena(); + invokeGetBool(() => realmLib.realm_set_size(pointer, outSize)); + return outSize.value; + }); + } + + bool get isValid { + return realmLib.realm_set_is_valid(pointer); + } + + void deleteAll() { + invokeGetBool(() => realmLib.realm_set_remove_all(pointer)); + } + + RealmNotificationTokenHandle subscribeForNotifications(NotificationsController controller) { + final ptr = invokeGetPointer(() => realmLib.realm_set_add_notification_callback( + pointer, + controller.toPersistentHandle(), + realmLib.addresses.realm_dart_delete_persistent_handle, + nullptr, + Pointer.fromFunction(collection_change_callback), + )); + return RealmNotificationTokenHandle._(ptr, _root); + } +} diff --git a/packages/realm_dart/lib/src/realm_class.dart b/packages/realm_dart/lib/src/realm_class.dart index aff6f63fc..3a07fb0ea 100644 --- a/packages/realm_dart/lib/src/realm_class.dart +++ b/packages/realm_dart/lib/src/realm_class.dart @@ -336,7 +336,7 @@ class Realm implements Finalizable { } else if (items is ManagedRealmSet) { _ensureManagedByThis(items, 'delete objects from Realm'); - realmCore.realmSetRemoveAll(items); + items.handle.deleteAll(); } else { for (T realmObject in items) { delete(realmObject); @@ -748,11 +748,11 @@ extension RealmInternal on Realm { return RealmListInternal.create(handle, this, metadata); } - RealmSet createSet(RealmSetHandle handle, RealmObjectMetadata? metadata) { + RealmSet createSet(SetHandle handle, RealmObjectMetadata? metadata) { return RealmSetInternal.create(handle, this, metadata); } - RealmMap createMap(RealmMapHandle handle, RealmObjectMetadata? metadata) { + RealmMap createMap(MapHandle handle, RealmObjectMetadata? metadata) { return RealmMapInternal.create(handle, this, metadata); } diff --git a/packages/realm_dart/lib/src/realm_object.dart b/packages/realm_dart/lib/src/realm_object.dart index 0d66110cf..6c7618b6a 100644 --- a/packages/realm_dart/lib/src/realm_object.dart +++ b/packages/realm_dart/lib/src/realm_object.dart @@ -284,7 +284,7 @@ class RealmCoreAccessor implements RealmAccessor { if (value is RealmSet) { final handle = realmCore.getSetProperty(object, propertyMeta.key); if (update) { - realmCore.realmSetClear(handle); + handle.clear(); } // TODO: use realmSetAssign when available in C-API @@ -293,7 +293,7 @@ class RealmCoreAccessor implements RealmAccessor { for (var element in value) { object.realm.addUnmanagedRealmObjectFromValue(element, update); - final result = realmCore.realmSetInsert(handle, element); + final result = handle.insert(element); if (!result) { throw RealmException("Error while adding value $element in RealmSet"); } @@ -304,7 +304,7 @@ class RealmCoreAccessor implements RealmAccessor { if (value is RealmMap) { final handle = realmCore.getMapProperty(object, propertyMeta.key); if (update) { - realmCore.mapClear(handle); + handle.clear(); } for (var kvp in value.entries) { diff --git a/packages/realm_dart/lib/src/set.dart b/packages/realm_dart/lib/src/set.dart index eb8fc4756..b48835ec6 100644 --- a/packages/realm_dart/lib/src/set.dart +++ b/packages/realm_dart/lib/src/set.dart @@ -122,7 +122,7 @@ class UnmanagedRealmSet extends collection.DelegatingSet w } class ManagedRealmSet with RealmEntity, SetMixin implements RealmSet { - final RealmSetHandle _handle; + final SetHandle _handle; ManagedRealmSet._(this._handle, Realm realm, this._metadata) { setRealm(realm); @@ -132,7 +132,7 @@ class ManagedRealmSet with RealmEntity, SetMixin implement late final RealmObjectMetadata? _metadata; @override - bool get isValid => realmCore.realmSetIsValid(this); + bool get isValid => handle.isValid; @override bool add(T value) { @@ -146,7 +146,7 @@ class ManagedRealmSet with RealmEntity, SetMixin implement realm.addUnmanagedRealmObjectFromValue(value, false); } - return realmCore.realmSetInsert(_handle, value); + return _handle.insert(value); } @override @@ -156,7 +156,7 @@ class ManagedRealmSet with RealmEntity, SetMixin implement } try { - var value = realmCore.realmSetGetElementAt(this, index); + var value = handle.elementAt(realm, index); if (value is ObjectHandle) { late RealmObjectMetadata targetMetadata; late Type type; @@ -188,7 +188,7 @@ class ManagedRealmSet with RealmEntity, SetMixin implement _ensureManagedByThis(element, "contains"); - return realmCore.realmSetFind(this, element); + return handle.find(element); } @override @@ -204,7 +204,7 @@ class ManagedRealmSet with RealmEntity, SetMixin implement _ensureManagedByThis(value, "remove"); - return realmCore.realmSetErase(this, value); + return handle.remove(value); } @override @@ -214,10 +214,10 @@ class ManagedRealmSet with RealmEntity, SetMixin implement Set toSet() => {...this}; @override - void clear() => realmCore.realmSetClear(_handle); + void clear() => _handle.clear(); @override - int get length => realmCore.realmSetSize(this); + int get length => handle.size; @override Stream> get changes { @@ -264,7 +264,7 @@ class ManagedRealmSet with RealmEntity, SetMixin implement } @override - RealmResults asResults() => RealmResultsInternal.create(realmCore.resultsFromSet(this), realm, _metadata); + RealmResults asResults() => RealmResultsInternal.create(handle.asResults, realm, _metadata); @override RealmSet freeze() { @@ -283,7 +283,7 @@ extension RealmSetInternal on RealmSet { RealmObjectMetadata? get metadata => asManaged()._metadata; - RealmSetHandle get handle { + SetHandle get handle { final result = asManaged()._handle; if (result.released) { throw RealmClosedError('Cannot access a RealmSet that belongs to a closed Realm'); @@ -292,7 +292,7 @@ extension RealmSetInternal on RealmSet { return result; } - static RealmSet create(RealmSetHandle handle, Realm realm, RealmObjectMetadata? metadata) => + static RealmSet create(SetHandle handle, Realm realm, RealmObjectMetadata? metadata) => ManagedRealmSet._(handle, realm, metadata); } @@ -339,7 +339,7 @@ class RealmSetNotificationsController extends NotificationsCo @override RealmNotificationTokenHandle subscribe() { - return realmCore.subscribeSetNotifications(set, this); + return set.handle.subscribeForNotifications(this); } Stream> createStream() { @@ -372,7 +372,7 @@ extension RealmSetOfObject on RealmSet { /// /// For more details about the syntax of the Realm Query Language, refer to the documentation: https://www.mongodb.com/docs/realm/realm-query-language/. RealmResults query(String query, [List arguments = const []]) { - final handle = realmCore.querySet(asManaged(), query, arguments); + final handle = asManaged().handle.query(query, arguments); return RealmResultsInternal.create(handle, realm, _metadata); } } From 769671d9c0a2daa40d150ab68ab814bbcbee9702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Mon, 15 Apr 2024 13:25:45 +0200 Subject: [PATCH 33/68] Refactor RealmAppCredentialsHandle (now CredentialsHandle) --- packages/realm_dart/lib/src/credentials.dart | 24 ++-- packages/realm_dart/lib/src/map.dart | 6 +- .../lib/src/native/credentials_handle.dart | 75 ++++++++++ .../realm_dart/lib/src/native/map_handle.dart | 16 +-- .../realm_dart/lib/src/native/realm_core.dart | 134 +----------------- .../lib/src/native/user_handle.dart | 2 +- 6 files changed, 101 insertions(+), 156 deletions(-) create mode 100644 packages/realm_dart/lib/src/native/credentials_handle.dart diff --git a/packages/realm_dart/lib/src/credentials.dart b/packages/realm_dart/lib/src/credentials.dart index d141a6e3d..9e09c13d0 100644 --- a/packages/realm_dart/lib/src/credentials.dart +++ b/packages/realm_dart/lib/src/credentials.dart @@ -57,44 +57,44 @@ extension AuthProviderTypeInternal on AuthProviderType { /// A class, representing the credentials used for authenticating a [User] /// {@category Application} class Credentials implements Finalizable { - final RealmAppCredentialsHandle _handle; + final CredentialsHandle _handle; /// Returns a [Credentials] object that can be used to authenticate an anonymous user. /// Setting [reuseCredentials] to `false` will create a new anonymous user, upon [App.logIn]. /// [Anonymous Authentication Docs](https://www.mongodb.com/docs/atlas/app-services/authentication/anonymous/#anonymous-authentication) - Credentials.anonymous({bool reuseCredentials = true}) : _handle = realmCore.createAppCredentialsAnonymous(reuseCredentials); + Credentials.anonymous({bool reuseCredentials = true}) : _handle = CredentialsHandle.anonymous(reuseCredentials); /// Returns a [Credentials] object that can be used to authenticate a user with a Google account using an id token. - Credentials.apple(String idToken) : _handle = realmCore.createAppCredentialsApple(idToken); + Credentials.apple(String idToken) : _handle = CredentialsHandle.apple(idToken); /// Returns a [Credentials] object that can be used to authenticate a user with their email and password. /// A user can login with email and password only after they have registered their account and verified their /// email. /// [Email/Password Authentication Docs](https://www.mongodb.com/docs/atlas/app-services/authentication/email-password/#email-password-authentication) - Credentials.emailPassword(String email, String password) : _handle = realmCore.createAppCredentialsEmailPassword(email, password); + Credentials.emailPassword(String email, String password) : _handle = CredentialsHandle.emailPassword(email, password); /// Returns a [Credentials] object that can be used to authenticate a user with a custom JWT. /// [Custom-JWT Authentication Docs](https://www.mongodb.com/docs/atlas/app-services/authentication/custom-jwt/#custom-jwt-authentication) - Credentials.jwt(String token) : _handle = realmCore.createAppCredentialsJwt(token); + Credentials.jwt(String token) : _handle = CredentialsHandle.jwt(token); /// Returns a [Credentials] object that can be used to authenticate a user with a Facebook account. - Credentials.facebook(String accessToken) : _handle = realmCore.createAppCredentialsFacebook(accessToken); + Credentials.facebook(String accessToken) : _handle = CredentialsHandle.facebook(accessToken); /// Returns a [Credentials] object that can be used to authenticate a user with a Google account using an authentication code. - Credentials.googleAuthCode(String authCode) : _handle = realmCore.createAppCredentialsGoogleAuthCode(authCode); + Credentials.googleAuthCode(String authCode) : _handle = CredentialsHandle.googleAuthCode(authCode); /// Returns a [Credentials] object that can be used to authenticate a user with a Google account using an id token. - Credentials.googleIdToken(String idToken) : _handle = realmCore.createAppCredentialsGoogleIdToken(idToken); + Credentials.googleIdToken(String idToken) : _handle = CredentialsHandle.googleIdToken(idToken); /// Returns a [Credentials] object that can be used to authenticate a user with a custom Function. /// [Custom Function Authentication Docs](https://www.mongodb.com/docs/atlas/app-services/authentication/custom-function/) - Credentials.function(String payload) : _handle = realmCore.createAppCredentialsFunction(payload); + Credentials.function(String payload) : _handle = CredentialsHandle.function(payload); /// Returns a [Credentials] object that can be used to authenticate a user with an API key. /// To generate an API key, use [ApiKeyClient.create] or the App Services web UI. - Credentials.apiKey(String key) : _handle = realmCore.createAppCredentialsApiKey(key); + Credentials.apiKey(String key) : _handle = CredentialsHandle.apiKey(key); - AuthProviderType get provider => realmCore.userGetCredentialsProviderType(this); + AuthProviderType get provider => handle.providerType; } /// @nodoc @@ -104,7 +104,7 @@ extension CredentialsInternal on Credentials { _handle.keepAlive(); } - RealmAppCredentialsHandle get handle => _handle; + CredentialsHandle get handle => _handle; } /// A class, encapsulating functionality for users, logged in with [Credentials.emailPassword()]. diff --git a/packages/realm_dart/lib/src/map.dart b/packages/realm_dart/lib/src/map.dart index 6e8c91880..dd406882d 100644 --- a/packages/realm_dart/lib/src/map.dart +++ b/packages/realm_dart/lib/src/map.dart @@ -262,19 +262,19 @@ extension RealmMapInternal on RealmMap { throw RealmError("Can't add to map an embedded object that is already managed"); } - final objHandle = realmCore.mapInsertEmbeddedObject(realm, handle, key); + final objHandle = handle.insertEmbedded(key); realm.manageEmbedded(objHandle, value); return; } if (value is RealmValue && value.type.isCollection) { - realmCore.mapInsertCollection(handle, realm, key, value); + handle.insertCollection(realm, key, value); return; } realm.addUnmanagedRealmObjectFromValue(value, update); - realmCore.mapInsertValue(handle, key, value); + handle.insert(key, value); } on Exception catch (e) { throw RealmException("Error setting value at key $key. Error: $e"); } diff --git a/packages/realm_dart/lib/src/native/credentials_handle.dart b/packages/realm_dart/lib/src/native/credentials_handle.dart new file mode 100644 index 000000000..5bb5e5fba --- /dev/null +++ b/packages/realm_dart/lib/src/native/credentials_handle.dart @@ -0,0 +1,75 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + +part of 'realm_core.dart'; + +class CredentialsHandle extends HandleBase { + CredentialsHandle._(Pointer pointer) : super(pointer, 16); + + factory CredentialsHandle.anonymous(bool reuseCredentials) { + return CredentialsHandle._(realmLib.realm_app_credentials_new_anonymous(reuseCredentials)); + } + + factory CredentialsHandle.emailPassword(String email, String password) { + return using((arena) { + final emailPtr = email.toCharPtr(arena); + final passwordPtr = password.toRealmString(arena); + return CredentialsHandle._(realmLib.realm_app_credentials_new_email_password(emailPtr, passwordPtr.ref)); + }); + } + + factory CredentialsHandle.jwt(String token) { + return using((arena) { + final tokenPtr = token.toCharPtr(arena); + return CredentialsHandle._(realmLib.realm_app_credentials_new_jwt(tokenPtr)); + }); + } + + factory CredentialsHandle.apple(String idToken) { + return using((arena) { + final idTokenPtr = idToken.toCharPtr(arena); + return CredentialsHandle._(realmLib.realm_app_credentials_new_apple(idTokenPtr)); + }); + } + + factory CredentialsHandle.facebook(String accessToken) { + return using((arena) { + final accessTokenPtr = accessToken.toCharPtr(arena); + return CredentialsHandle._(realmLib.realm_app_credentials_new_facebook(accessTokenPtr)); + }); + } + + factory CredentialsHandle.googleIdToken(String idToken) { + return using((arena) { + final idTokenPtr = idToken.toCharPtr(arena); + return CredentialsHandle._(realmLib.realm_app_credentials_new_google_id_token(idTokenPtr)); + }); + } + + factory CredentialsHandle.googleAuthCode(String authCode) { + return using((arena) { + final authCodePtr = authCode.toCharPtr(arena); + return CredentialsHandle._(realmLib.realm_app_credentials_new_google_auth_code(authCodePtr)); + }); + } + + factory CredentialsHandle.function(String payload) { + return using((arena) { + final payloadPtr = payload.toCharPtr(arena); + final credentialsPtr = invokeGetPointer(() => realmLib.realm_app_credentials_new_function(payloadPtr)); + return CredentialsHandle._(credentialsPtr); + }); + } + + factory CredentialsHandle.apiKey(String key) { + return using((arena) { + final keyPtr = key.toCharPtr(arena); + return CredentialsHandle._(realmLib.realm_app_credentials_new_api_key(keyPtr)); + }); + } + + AuthProviderType get providerType { + final provider = realmLib.realm_auth_credentials_get_provider(pointer); + return AuthProviderTypeInternal.getByValue(provider); + } +} diff --git a/packages/realm_dart/lib/src/native/map_handle.dart b/packages/realm_dart/lib/src/native/map_handle.dart index fceadf4ef..058a4471b 100644 --- a/packages/realm_dart/lib/src/native/map_handle.dart +++ b/packages/realm_dart/lib/src/native/map_handle.dart @@ -84,21 +84,21 @@ class MapHandle extends CollectionHandleBase { bool containsValue(Object? value) => indexOf(value) > -1; - ObjectHandle mapInsertEmbeddedObject(Realm realm, MapHandle handle, String key) { + ObjectHandle insertEmbedded(String key) { return using((Arena arena) { final keyNative = _toRealmValue(key, arena); - final ptr = invokeGetPointer(() => realmLib.realm_dictionary_insert_embedded(handle.pointer, keyNative.ref)); - return ObjectHandle._(ptr, realm.handle); + final ptr = invokeGetPointer(() => realmLib.realm_dictionary_insert_embedded(pointer, keyNative.ref)); + return ObjectHandle._(ptr, _root); }); } - void mapInsertValue(MapHandle handle, String key, Object? value) { + void insert(String key, Object? value) { using((Arena arena) { final keyNative = _toRealmValue(key, arena); final valueNative = _toRealmValue(value, arena); invokeGetBool( () => realmLib.realm_dictionary_insert( - handle.pointer, + pointer, keyNative.ref, valueNative.ref, nullptr, @@ -108,14 +108,14 @@ class MapHandle extends CollectionHandleBase { }); } - void mapInsertCollection(MapHandle handle, Realm realm, String key, RealmValue value) { + void insertCollection(Realm realm, String key, RealmValue value) { using((Arena arena) { final keyNative = _toRealmValue(key, arena); _createCollection( realm, value, - () => realmLib.realm_dictionary_insert_list(handle.pointer, keyNative.ref), - () => realmLib.realm_dictionary_insert_dictionary(handle.pointer, keyNative.ref), + () => realmLib.realm_dictionary_insert_list(pointer, keyNative.ref), + () => realmLib.realm_dictionary_insert_dictionary(pointer, keyNative.ref), ); }); } diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 7b6ac059c..c788b282a 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -40,10 +40,11 @@ import 'handle_base.dart'; import 'realm_bindings.dart'; import 'realm_library.dart'; -// TODO: Use regular +// TODO: Use regular imports part 'app_handle.dart'; part 'config_handle.dart'; part 'convert.dart'; +part 'credentials_handle.dart'; part 'decimal128.dart'; part 'error_handling.dart'; part 'list_handle.dart'; @@ -902,30 +903,6 @@ class _RealmCore { return SetHandle._(pointer, object.realm.handle); } - ObjectHandle mapInsertEmbeddedObject(Realm realm, MapHandle handle, String key) { - return using((Arena arena) { - final realm_value = _toRealmValue(key, arena); - final ptr = invokeGetPointer(() => realmLib.realm_dictionary_insert_embedded(handle.pointer, realm_value.ref)); - return ObjectHandle._(ptr, realm.handle); - }); - } - - void mapInsertValue(MapHandle handle, String key, Object? value) { - using((Arena arena) { - final key_value = _toRealmValue(key, arena); - final value_value = _toRealmValue(value, arena); - invokeGetBool(() => realmLib.realm_dictionary_insert(handle.pointer, key_value.ref, value_value.ref, nullptr, nullptr)); - }); - } - - void mapInsertCollection(MapHandle handle, Realm realm, String key, RealmValue value) { - using((Arena arena) { - final key_value = _toRealmValue(key, arena); - _createCollection(realm, value, () => realmLib.realm_dictionary_insert_list(handle.pointer, key_value.ref), - () => realmLib.realm_dictionary_insert_dictionary(handle.pointer, key_value.ref)); - }); - } - MapHandle getMapProperty(RealmObjectBase object, int propertyKey) { final pointer = invokeGetPointer(() => realmLib.realm_get_dictionary(object.handle.pointer, propertyKey)); return MapHandle._(pointer, object.realm.handle); @@ -1031,104 +1008,6 @@ class _RealmCore { }); } - AppConfigHandle _createAppConfig(AppConfiguration configuration, RealmHttpTransportHandle httpTransport) { - return using((arena) { - final app_id = configuration.appId.toCharPtr(arena); - final handle = AppConfigHandle._(realmLib.realm_app_config_new(app_id, httpTransport.pointer)); - - realmLib.realm_app_config_set_platform_version(handle.pointer, Platform.operatingSystemVersion.toCharPtr(arena)); - - realmLib.realm_app_config_set_sdk(handle.pointer, 'Dart'.toCharPtr(arena)); - realmLib.realm_app_config_set_sdk_version(handle.pointer, libraryVersion.toCharPtr(arena)); - - final deviceName = getDeviceName(); - realmLib.realm_app_config_set_device_name(handle.pointer, deviceName.toCharPtr(arena)); - - final deviceVersion = getDeviceVersion(); - realmLib.realm_app_config_set_device_version(handle.pointer, deviceVersion.toCharPtr(arena)); - - realmLib.realm_app_config_set_framework_name(handle.pointer, (isFlutterPlatform ? 'Flutter' : 'Dart VM').toCharPtr(arena)); - realmLib.realm_app_config_set_framework_version(handle.pointer, Platform.version.toCharPtr(arena)); - - realmLib.realm_app_config_set_base_url(handle.pointer, configuration.baseUrl.toString().toCharPtr(arena)); - - realmLib.realm_app_config_set_default_request_timeout(handle.pointer, configuration.defaultRequestTimeout.inMilliseconds); - - realmLib.realm_app_config_set_bundle_id(handle.pointer, getBundleId().toCharPtr(arena)); - - _realmLib.realm_app_config_set_base_file_path(handle._pointer, configuration.baseFilePath.path.toCharPtr(arena)); - _realmLib.realm_app_config_set_metadata_mode(handle._pointer, configuration.metadataPersistenceMode.index); - _realmLib.realm_app_config_set_default_request_timeout(handle._pointer, configuration.defaultRequestTimeout.inMilliseconds); - if (configuration.metadataEncryptionKey != null && configuration.metadataPersistenceMode == MetadataPersistenceMode.encrypted) { - _realmLib.realm_app_config_set_metadata_encryption_key(handle._pointer, configuration.metadataEncryptionKey!.toUint8Ptr(arena)); - } - - return handle; - }); - } - - RealmAppCredentialsHandle createAppCredentialsAnonymous(bool reuseCredentials) { - return RealmAppCredentialsHandle._(realmLib.realm_app_credentials_new_anonymous(reuseCredentials)); - } - - RealmAppCredentialsHandle createAppCredentialsEmailPassword(String email, String password) { - return using((arena) { - final emailPtr = email.toCharPtr(arena); - final passwordPtr = password.toRealmString(arena); - return RealmAppCredentialsHandle._(realmLib.realm_app_credentials_new_email_password(emailPtr, passwordPtr.ref)); - }); - } - - RealmAppCredentialsHandle createAppCredentialsJwt(String token) { - return using((arena) { - final tokenPtr = token.toCharPtr(arena); - return RealmAppCredentialsHandle._(realmLib.realm_app_credentials_new_jwt(tokenPtr)); - }); - } - - RealmAppCredentialsHandle createAppCredentialsApple(String idToken) { - return using((arena) { - final idTokenPtr = idToken.toCharPtr(arena); - return RealmAppCredentialsHandle._(realmLib.realm_app_credentials_new_apple(idTokenPtr)); - }); - } - - RealmAppCredentialsHandle createAppCredentialsFacebook(String accessToken) { - return using((arena) { - final accessTokenPtr = accessToken.toCharPtr(arena); - return RealmAppCredentialsHandle._(realmLib.realm_app_credentials_new_facebook(accessTokenPtr)); - }); - } - - RealmAppCredentialsHandle createAppCredentialsGoogleIdToken(String idToken) { - return using((arena) { - final idTokenPtr = idToken.toCharPtr(arena); - return RealmAppCredentialsHandle._(realmLib.realm_app_credentials_new_google_id_token(idTokenPtr)); - }); - } - - RealmAppCredentialsHandle createAppCredentialsGoogleAuthCode(String authCode) { - return using((arena) { - final authCodePtr = authCode.toCharPtr(arena); - return RealmAppCredentialsHandle._(realmLib.realm_app_credentials_new_google_auth_code(authCodePtr)); - }); - } - - RealmAppCredentialsHandle createAppCredentialsFunction(String payload) { - return using((arena) { - final payloadPtr = payload.toCharPtr(arena); - final credentialsPtr = invokeGetPointer(() => realmLib.realm_app_credentials_new_function(payloadPtr)); - return RealmAppCredentialsHandle._(credentialsPtr); - }); - } - - RealmAppCredentialsHandle createAppCredentialsApiKey(String key) { - return using((arena) { - final keyPtr = key.toCharPtr(arena); - return RealmAppCredentialsHandle._(realmLib.realm_app_credentials_new_api_key(keyPtr)); - }); - } - void logMessage(LogCategory category, LogLevel logLevel, String message) { return using((arena) { realmLib.realm_dart_log(logLevel.index, category.toString().toCharPtr(arena), message.toCharPtr(arena)); @@ -1151,11 +1030,6 @@ class _RealmCore { realmLib.realm_clear_cached_apps(); } - AuthProviderType userGetCredentialsProviderType(Credentials credentials) { - final provider = realmLib.realm_auth_credentials_get_provider(credentials.handle.pointer); - return AuthProviderTypeInternal.getByValue(provider); - } - RealmSyncSessionConnectionStateNotificationTokenHandle sessionRegisterProgressNotifier( Session session, ProgressDirection direction, ProgressMode mode, SessionProgressNotificationsController controller) { final isStreaming = mode == ProgressMode.reportIndefinitely; @@ -1368,10 +1242,6 @@ class RealmObjectChangesHandle extends HandleBase { RealmObjectChangesHandle._(Pointer pointer) : super(pointer, 256); } -class RealmAppCredentialsHandle extends HandleBase { - RealmAppCredentialsHandle._(Pointer pointer) : super(pointer, 16); -} - class RealmAsyncOpenTaskHandle extends HandleBase { RealmAsyncOpenTaskHandle._(Pointer pointer) : super(pointer, 32); } diff --git a/packages/realm_dart/lib/src/native/user_handle.dart b/packages/realm_dart/lib/src/native/user_handle.dart index 9e91d5e48..4457d3b18 100644 --- a/packages/realm_dart/lib/src/native/user_handle.dart +++ b/packages/realm_dart/lib/src/native/user_handle.dart @@ -90,7 +90,7 @@ class UserHandle extends HandleBase { return customDataPtr.cast().toRealmDartString(freeRealmMemory: true, treatEmptyAsNull: true); } - Future linkCredentials(AppHandle app, RealmAppCredentialsHandle credentials) { + Future linkCredentials(AppHandle app, CredentialsHandle credentials) { final completer = Completer(); invokeGetBool( () => realmLib.realm_app_link_user( From e5addc386fb35d00c6cfa7dd87c5ad0a46cf994b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Tue, 16 Apr 2024 11:09:49 +0200 Subject: [PATCH 34/68] WIP --- packages/realm_dart/lib/src/list.dart | 2 +- packages/realm_dart/lib/src/map.dart | 2 +- .../lib/src/native/object_handle.dart | 97 ++++++++++++++++--- .../realm_dart/lib/src/native/realm_core.dart | 94 ------------------ .../lib/src/native/realm_handle.dart | 6 ++ packages/realm_dart/lib/src/realm_class.dart | 18 ++-- packages/realm_dart/lib/src/realm_object.dart | 30 +++--- packages/realm_dart/lib/src/results.dart | 2 +- packages/realm_dart/lib/src/set.dart | 2 +- packages/realm_dart/test/test.dart | 2 +- 10 files changed, 120 insertions(+), 135 deletions(-) diff --git a/packages/realm_dart/lib/src/list.dart b/packages/realm_dart/lib/src/list.dart index 01546d245..155f86610 100644 --- a/packages/realm_dart/lib/src/list.dart +++ b/packages/realm_dart/lib/src/list.dart @@ -105,7 +105,7 @@ class ManagedRealmList with RealmEntity, ListMixin impleme late RealmObjectMetadata targetMetadata; late Type type; if (T == RealmValue) { - (type, targetMetadata) = realm.metadata.getByClassKey(value.getClassKey()); + (type, targetMetadata) = realm.metadata.getByClassKey(value.classKey); } else { targetMetadata = _metadata!; type = T; diff --git a/packages/realm_dart/lib/src/map.dart b/packages/realm_dart/lib/src/map.dart index dd406882d..b27e766b5 100644 --- a/packages/realm_dart/lib/src/map.dart +++ b/packages/realm_dart/lib/src/map.dart @@ -97,7 +97,7 @@ class ManagedRealmMap with RealmEntity, MapMixin i late RealmObjectMetadata targetMetadata; late Type type; if (T == RealmValue) { - (type, targetMetadata) = realm.metadata.getByClassKey(value.getClassKey()); + (type, targetMetadata) = realm.metadata.getByClassKey(value.classKey); } else { targetMetadata = _metadata!; type = T; diff --git a/packages/realm_dart/lib/src/native/object_handle.dart b/packages/realm_dart/lib/src/native/object_handle.dart index 5864fffee..01465a533 100644 --- a/packages/realm_dart/lib/src/native/object_handle.dart +++ b/packages/realm_dart/lib/src/native/object_handle.dart @@ -11,35 +11,67 @@ class ObjectHandle extends RootedHandleBase { return ObjectHandle._(objectPtr, _root); } - int getClassKey() => realmLib.realm_object_get_table(pointer); + int get classKey => realmLib.realm_object_get_table(pointer); -/* - Object? getProperty(int propertyKey) { + bool get isValid => realmLib.realm_object_is_valid(pointer); + + // TODO: avoid taking the [realm] parameter + Object? getValue(Realm realm, int propertyKey) { return using((Arena arena) { final realmValue = arena(); invokeGetBool(() => realmLib.realm_get_value(pointer, propertyKey, realmValue)); return realmValue.toDartValue( - object.realm, + realm, () => realmLib.realm_get_list(pointer, propertyKey), () => realmLib.realm_get_dictionary(pointer, propertyKey), ); }); } -*/ - void setProperty(int propertyKey, Object? value, bool isDefault) { + // TODO: value should be RealmValue, and perhaps this method should be combined + // with setCollection? + void setValue(int propertyKey, Object? value, bool isDefault) { using((Arena arena) { final realmValue = _toRealmValue(value, arena); - invokeGetBool(() => realmLib.realm_set_value(pointer, propertyKey, realmValue.ref, isDefault)); + invokeGetBool( + () => realmLib.realm_set_value( + pointer, + propertyKey, + realmValue.ref, + isDefault, + ), + ); }); } -/* - void objectSetCollection(int propertyKey, RealmValue value) { - _createCollection(object.realm, value, () => realmLib.realm_set_list(pointer, propertyKey), - () => realmLib.realm_set_dictionary(pointer, propertyKey)); + ListHandle getList(int propertyKey) { + final ptr = invokeGetPointer(() => realmLib.realm_get_list(pointer, propertyKey)); + return ListHandle._(ptr, _root); + } + + SetHandle getSet(int propertyKey) { + final ptr = invokeGetPointer(() => realmLib.realm_get_set(pointer, propertyKey)); + return SetHandle._(ptr, _root); + } + + MapHandle getMap(int propertyKey) { + final ptr = invokeGetPointer(() => realmLib.realm_get_dictionary(pointer, propertyKey)); + return MapHandle._(ptr, _root); + } + + ResultsHandle getBacklinks(int sourceTableKey, int propertyKey) { + final ptr = invokeGetPointer(() => realmLib.realm_get_backlinks(pointer, sourceTableKey, propertyKey)); + return ResultsHandle._(ptr, _root); + } + + void setCollection(Realm realm, int propertyKey, RealmValue value) { + _createCollection( + realm, + value, + () => realmLib.realm_set_list(pointer, propertyKey), + () => realmLib.realm_set_dictionary(pointer, propertyKey), + ); } -*/ String objectToString() { return realmLib.realm_object_to_string(pointer).cast().toRealmDartString(freeRealmMemory: true)!; @@ -48,4 +80,45 @@ class ObjectHandle extends RootedHandleBase { void delete() { invokeGetBool(() => realmLib.realm_object_delete(pointer)); } + + ObjectHandle? resolveIn(RealmHandle frozenRealm) { + return using((Arena arena) { + final resultPtr = arena>(); + invokeGetBool(() => realmLib.realm_object_resolve_in(pointer, frozenRealm.pointer, resultPtr)); + return resultPtr == nullptr ? null : ObjectHandle._(resultPtr.value, frozenRealm); + }); + } + + RealmNotificationTokenHandle subscribeForNotifications(NotificationsController controller, [List? keyPaths]) { + return using((Arena arena) { + final kpNative = buildAndVerifyKeyPath(keyPaths); + final ptr = invokeGetPointer(() => realmLib.realm_object_add_notification_callback( + pointer, + controller.toPersistentHandle(), + realmLib.addresses.realm_dart_delete_persistent_handle, + kpNative, + Pointer.fromFunction(object_change_callback), + )); + + return RealmNotificationTokenHandle._(ptr, _root); + }); + } + + Pointer buildAndVerifyKeyPath(List? keyPaths) { + return using((Arena arena) { + if (keyPaths == null) { + return nullptr; + } + + final length = keyPaths.length; + final keypathsNative = arena>(length); + + for (int i = 0; i < length; i++) { + keypathsNative[i] = keyPaths[i].toCharPtr(arena); + } + // TODO(kn): + // call to classKey getter involves a native call, which is not ideal + return invokeGetPointer(() => realmLib.realm_create_key_path_array(_root.pointer, classKey, length, keypathsNative)); + }); + } } diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index c788b282a..4d30deaef 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -522,12 +522,6 @@ class _RealmCore { realmLib.realm_scheduler_perform_work(queuePointer); } - RealmHandle openRealm(Configuration config) { - final configHandle = ConfigHandle(config); - final realmPtr = invokeGetPointer(() => realmLib.realm_open(configHandle.pointer), "Error opening realm at path ${config.path}"); - return RealmHandle._(realmPtr); - } - RealmAsyncOpenTaskHandle createRealmAsyncOpenTask(FlexibleSyncConfiguration config) { final configHandle = ConfigHandle(config); final asyncOpenTaskPtr = invokeGetPointer(() => realmLib.realm_open_synchronized(configHandle.pointer), "Error opening realm at path ${config.path}"); @@ -718,29 +712,6 @@ class _RealmCore { }); } - Object? getProperty(RealmObjectBase object, int propertyKey) { - return using((Arena arena) { - final realm_value = arena(); - invokeGetBool(() => realmLib.realm_get_value(object.handle.pointer, propertyKey, realm_value)); - return realm_value.toDartValue(object.realm, () => realmLib.realm_get_list(object.handle.pointer, propertyKey), - () => realmLib.realm_get_dictionary(object.handle.pointer, propertyKey)); - }); - } - - void setProperty(RealmObjectBase object, int propertyKey, Object? value, bool isDefault) { - using((Arena arena) { - final realm_value = _toRealmValue(value, arena); - invokeGetBool(() => realmLib.realm_set_value(object.handle.pointer, propertyKey, realm_value.ref, isDefault)); - }); - } - - void objectSetCollection(RealmObjectBase object, int propertyKey, RealmValue value) { - _createCollection(object.realm, value, () => realmLib.realm_set_list(object.handle.pointer, propertyKey), - () => realmLib.realm_set_dictionary(object.handle.pointer, propertyKey)); - } - - String objectToString(RealmObjectBase object) => object.handle.objectToString(); - // For debugging // ignore: unused_element int get _threadId => realmLib.realm_dart_get_thread_id(); @@ -888,26 +859,6 @@ class _RealmCore { return ObjectHandle._(pointer, realm.handle); } - ListHandle getListProperty(RealmObjectBase object, int propertyKey) { - final pointer = invokeGetPointer(() => realmLib.realm_get_list(object.handle.pointer, propertyKey)); - return ListHandle._(pointer, object.realm.handle); - } - - ResultsHandle getBacklinks(RealmObjectBase object, int sourceTableKey, int propertyKey) { - final pointer = invokeGetPointer(() => realmLib.realm_get_backlinks(object.handle.pointer, sourceTableKey, propertyKey)); - return ResultsHandle._(pointer, object.realm.handle); - } - - SetHandle getSetProperty(RealmObjectBase object, int propertyKey) { - final pointer = invokeGetPointer(() => realmLib.realm_get_set(object.handle.pointer, propertyKey)); - return SetHandle._(pointer, object.realm.handle); - } - - MapHandle getMapProperty(RealmObjectBase object, int propertyKey) { - final pointer = invokeGetPointer(() => realmLib.realm_get_dictionary(object.handle.pointer, propertyKey)); - return MapHandle._(pointer, object.realm.handle); - } - bool _equals(HandleBase first, HandleBase second) { return realmLib.realm_equals(first.pointer.cast(), second.pointer.cast()); } @@ -925,10 +876,6 @@ class _RealmCore { return hashCode; } - bool objectIsValid(RealmObjectBase object) { - return realmLib.realm_object_is_valid(object.handle.pointer); - } - RealmNotificationTokenHandle subscribeResultsNotifications(RealmResults results, NotificationsController controller) { final pointer = invokeGetPointer(() => realmLib.realm_results_add_notification_callback( results.handle.pointer, @@ -941,39 +888,6 @@ class _RealmCore { return RealmNotificationTokenHandle._(pointer, results.realm.handle); } - RealmNotificationTokenHandle subscribeObjectNotifications(RealmObjectBase object, NotificationsController controller, [List? keyPaths]) { - return using((Arena arena) { - final kpNative = buildAndVerifyKeyPath(object, keyPaths); - final pointer = invokeGetPointer(() => realmLib.realm_object_add_notification_callback( - object.handle._pointer, - controller.toPersistentHandle(), - realmLib.addresses.realm_dart_delete_persistent_handle, - kpNative, - Pointer.fromFunction(object_change_callback), - )); - - return RealmNotificationTokenHandle._(pointer, object.realm.handle); - }); - } - - Pointer buildAndVerifyKeyPath(RealmObjectBase object, [List? keyPaths]) { - return using((Arena arena) { - if (keyPaths == null) { - return nullptr; - } - - final length = keyPaths.length; - final keypathsNative = arena>(length); - final classKey = object.realm.metadata.getByName(object.objectSchema.name).classKey; - - for (int i = 0; i < length; i++) { - keypathsNative[i] = keyPaths[i].toCharPtr(arena); - } - - return invokeGetPointer(() => realmLib.realm_create_key_path_array(object.realm.handle._pointer, classKey, length, keypathsNative)); - }); - } - UserNotificationTokenHandle subscribeUserNotifications(UserNotificationsController controller) { final callback = Pointer.fromFunction(user_change_callback); final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); @@ -1112,14 +1026,6 @@ class _RealmCore { ResultsHandle resolveResults(RealmResults realmResults, Realm frozenRealm) => realmResults.handle.resolveIn(frozenRealm.handle); - ObjectHandle? resolveObject(RealmObjectBase object, Realm frozenRealm) { - return using((Arena arena) { - final resultPtr = arena>(); - invokeGetBool(() => realmLib.realm_object_resolve_in(object.handle.pointer, frozenRealm.handle.pointer, resultPtr)); - return resultPtr == nullptr ? null : ObjectHandle._(resultPtr.value, frozenRealm.handle); - }); - } - ListHandle? resolveList(ManagedRealmList list, Realm frozenRealm) { return using((Arena arena) { final resultPtr = arena>(); diff --git a/packages/realm_dart/lib/src/native/realm_handle.dart b/packages/realm_dart/lib/src/native/realm_handle.dart index b34403c93..058d6f715 100644 --- a/packages/realm_dart/lib/src/native/realm_handle.dart +++ b/packages/realm_dart/lib/src/native/realm_handle.dart @@ -12,6 +12,12 @@ class RealmHandle extends HandleBase { RealmHandle._unowned(super.pointer) : super.unowned(); + factory RealmHandle.open(Configuration config) { + final configHandle = ConfigHandle(config); + final realmPtr = invokeGetPointer(() => realmLib.realm_open(configHandle.pointer), 'Error opening realm at path ${config.path}'); + return RealmHandle._(realmPtr); + } + int addChild(RootedHandleBase child) { final id = _counter++; _children[id] = WeakReference(child); diff --git a/packages/realm_dart/lib/src/realm_class.dart b/packages/realm_dart/lib/src/realm_class.dart index 3a07fb0ea..5791db194 100644 --- a/packages/realm_dart/lib/src/realm_class.dart +++ b/packages/realm_dart/lib/src/realm_class.dart @@ -198,7 +198,7 @@ class Realm implements Finalizable { static RealmHandle _openRealm(Configuration config) { _ensureDirectory(config); - return realmCore.openRealm(config); + return RealmHandle.open(config); } static void _ensureDirectory(Configuration config) { @@ -780,8 +780,8 @@ extension RealmInternal on Realm { /// This should only be used for testing RealmResults allEmbedded() { final metadata = _metadata.getByType(T); - final handle = this.handle.findAll(metadata.classKey); - return RealmResultsInternal.create(handle, this, metadata); + final resultsHandle = handle.findAll(metadata.classKey); + return RealmResultsInternal.create(resultsHandle, this, metadata); } T? resolveObject(T object) { @@ -793,23 +793,23 @@ extension RealmInternal on Realm { throw RealmStateError("Can't resolve invalidated (deleted) objects"); } - final handle = realmCore.resolveObject(object, this); - if (handle == null) { + final newHandle = object.handle.resolveIn(handle); + if (newHandle == null) { return null; } final metadata = (object.accessor as RealmCoreAccessor).metadata; - return RealmObjectInternal.create(T, this, handle, RealmCoreAccessor(metadata, _isInMigration)) as T; + return RealmObjectInternal.create(T, this, newHandle, RealmCoreAccessor(metadata, _isInMigration)) as T; } RealmList? resolveList(ManagedRealmList list) { - final handle = realmCore.resolveList(list, this); - if (handle == null) { + final resultHandle = realmCore.resolveList(list, this); + if (resultHandle == null) { return null; } - return createList(handle, list.metadata); + return createList(resultHandle, list.metadata); } RealmResults resolveResults(RealmResults results) { diff --git a/packages/realm_dart/lib/src/realm_object.dart b/packages/realm_dart/lib/src/realm_object.dart index 6c7618b6a..b624ae170 100644 --- a/packages/realm_dart/lib/src/realm_object.dart +++ b/packages/realm_dart/lib/src/realm_object.dart @@ -158,11 +158,11 @@ class RealmCoreAccessor implements RealmAccessor { if (propertyMeta.propertyType == RealmPropertyType.linkingObjects) { final sourceMeta = object.realm.metadata.getByName(propertyMeta.objectType!); final sourceProperty = sourceMeta[propertyMeta.linkOriginProperty!]; - final handle = realmCore.getBacklinks(object, sourceMeta.classKey, sourceProperty.key); + final handle = object.handle.getBacklinks(sourceMeta.classKey, sourceProperty.key); return RealmResultsInternal.create(handle, object.realm, sourceMeta); } - final handle = realmCore.getListProperty(object, propertyMeta.key); + final handle = object.handle.getList(propertyMeta.key); final listMetadata = propertyMeta.objectType == null ? null : object.realm.metadata.getByName(propertyMeta.objectType!); if (propertyMeta.propertyType == RealmPropertyType.mixed) { @@ -186,7 +186,7 @@ class RealmCoreAccessor implements RealmAccessor { } return object.realm.createList(handle, listMetadata); case RealmCollectionType.set: - final handle = realmCore.getSetProperty(object, propertyMeta.key); + final handle = object.handle.getSet(propertyMeta.key); final setMetadata = propertyMeta.objectType == null ? null : object.realm.metadata.getByName(propertyMeta.objectType!); if (setMetadata != null && _isTypeGenericObject()) { switch (setMetadata.schema.baseType) { @@ -203,7 +203,7 @@ class RealmCoreAccessor implements RealmAccessor { return object.realm.createSet(handle, setMetadata); case RealmCollectionType.map: - final handle = realmCore.getMapProperty(object, propertyMeta.key); + final handle = object.handle.getMap(propertyMeta.key); final mapMetadata = propertyMeta.objectType == null ? null : object.realm.metadata.getByName(propertyMeta.objectType!); if (propertyMeta.propertyType == RealmPropertyType.mixed) { @@ -227,7 +227,7 @@ class RealmCoreAccessor implements RealmAccessor { } return object.realm.createMap(handle, mapMetadata); default: - var value = realmCore.getProperty(object, propertyMeta.key); + var value = object.handle.getValue(object.realm, propertyMeta.key); if (value is ObjectHandle) { final meta = object.realm.metadata; @@ -237,7 +237,7 @@ class RealmCoreAccessor implements RealmAccessor { late RealmObjectMetadata targetMetadata; if (propertyMeta.propertyType == RealmPropertyType.mixed) { - (type, targetMetadata) = meta.getByClassKey(value.getClassKey()); + (type, targetMetadata) = meta.getByClassKey(value.classKey); } else { // If we have an object but the user called the API without providing a generic // arg, we construct a RealmObject since we don't know the type of the object. @@ -264,12 +264,12 @@ class RealmCoreAccessor implements RealmAccessor { final propertyMeta = metadata[name]; try { if (value is RealmValue && value.type.isCollection) { - realmCore.objectSetCollection(object, propertyMeta.key, value); + object.handle.setCollection(object.realm, propertyMeta.key, value); return; } if (value is RealmList) { - final handle = realmCore.getListProperty(object, propertyMeta.key); + final handle = object.handle.getList(propertyMeta.key); if (update) { handle.clear(); } @@ -282,7 +282,7 @@ class RealmCoreAccessor implements RealmAccessor { //TODO: set from ManagedRealmList is not supported yet if (value is RealmSet) { - final handle = realmCore.getSetProperty(object, propertyMeta.key); + final handle = object.handle.getSet(propertyMeta.key); if (update) { handle.clear(); } @@ -302,7 +302,7 @@ class RealmCoreAccessor implements RealmAccessor { } if (value is RealmMap) { - final handle = realmCore.getMapProperty(object, propertyMeta.key); + final handle = object.handle.getMap(propertyMeta.key); if (update) { handle.clear(); } @@ -326,13 +326,13 @@ class RealmCoreAccessor implements RealmAccessor { object.realm.addUnmanagedRealmObjectFromValue(value, update); if (propertyMeta.isPrimaryKey && !isInMigration) { - final currentValue = realmCore.getProperty(object, propertyMeta.key); + final currentValue = object.handle.getValue(object.realm, propertyMeta.key); if (currentValue != value) { throw RealmException("Primary key cannot be changed (original value: '$currentValue', supplied value: '$value')"); } } - realmCore.setProperty(object, propertyMeta.key, value, isDefault); + object.handle.setValue(propertyMeta.key, value, isDefault); } on Exception catch (e) { throw RealmException("Error setting property ${metadata._realmObjectTypeName}.$name Error: $e"); } @@ -476,7 +476,7 @@ mixin RealmObjectBase on RealmEntity implements RealmObjectBaseMarker, Finalizab /// will throw an exception. /// The Object is not valid if its [Realm] is closed or object is deleted. /// Unmanaged objects are always considered valid. - bool get isValid => isManaged ? realmCore.objectIsValid(this) : true; + bool get isValid => isManaged ? handle.isValid : true; /// Allows listening for property changes on this Realm object. /// @@ -598,7 +598,7 @@ mixin RealmObjectBase on RealmEntity implements RealmObjectBaseMarker, Finalizab throw RealmError( "Property $T.$propertyName is a link property that links to ${sourceProperty.objectType} which is different from the type of the current object, which is $runtimeType."); } - final handle = realmCore.getBacklinks(this, sourceMeta.classKey, sourceProperty.key); + final handle = this.handle.getBacklinks(sourceMeta.classKey, sourceProperty.key); return RealmResultsInternal.create(handle, realm, sourceMeta); } @@ -774,7 +774,7 @@ class RealmObjectNotificationsController extends Noti @override RealmNotificationTokenHandle subscribe() { - return realmCore.subscribeObjectNotifications(realmObject, this, keyPaths); + return realmObject.handle.subscribeForNotifications(this, keyPaths); } Stream> createStream() { diff --git a/packages/realm_dart/lib/src/results.dart b/packages/realm_dart/lib/src/results.dart index da97d3ff4..5987a6bd2 100644 --- a/packages/realm_dart/lib/src/results.dart +++ b/packages/realm_dart/lib/src/results.dart @@ -48,7 +48,7 @@ class RealmResults extends Iterable with RealmEntity imple late RealmObjectMetadata targetMetadata; late Type type; if (T == RealmValue) { - (type, targetMetadata) = realm.metadata.getByClassKey(value.getClassKey()); + (type, targetMetadata) = realm.metadata.getByClassKey(value.classKey); } else { targetMetadata = _metadata!; type = T; diff --git a/packages/realm_dart/lib/src/set.dart b/packages/realm_dart/lib/src/set.dart index b48835ec6..3aea3332a 100644 --- a/packages/realm_dart/lib/src/set.dart +++ b/packages/realm_dart/lib/src/set.dart @@ -161,7 +161,7 @@ class ManagedRealmSet with RealmEntity, SetMixin implement late RealmObjectMetadata targetMetadata; late Type type; if (T == RealmValue) { - (type, targetMetadata) = realm.metadata.getByClassKey(value.getClassKey()); + (type, targetMetadata) = realm.metadata.getByClassKey(value.classKey); } else { targetMetadata = _metadata!; // will be null for RealmValue, so defer until here type = T; diff --git a/packages/realm_dart/test/test.dart b/packages/realm_dart/test/test.dart index 12fe85cef..025966f11 100644 --- a/packages/realm_dart/test/test.dart +++ b/packages/realm_dart/test/test.dart @@ -673,7 +673,7 @@ Future waitForConditionWithResult(FutureOr Function() getter, FutureOr< } extension RealmObjectTest on RealmObjectBase { - String toJson() => realmCore.objectToString(this); + String toJson() => this.handle.objectToString(); } extension on int { From f0f1e03c262dc02ccd141f72aa557d27f98a5b6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Thu, 18 Apr 2024 16:05:43 +0200 Subject: [PATCH 35/68] WIP2 --- packages/realm_dart/lib/src/realm_object.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/realm_dart/lib/src/realm_object.dart b/packages/realm_dart/lib/src/realm_object.dart index b624ae170..b012f10d1 100644 --- a/packages/realm_dart/lib/src/realm_object.dart +++ b/packages/realm_dart/lib/src/realm_object.dart @@ -768,7 +768,8 @@ class RealmObjectNotificationsController extends Noti if (keyPaths.any((element) => element.isEmpty)) { throw RealmException("It is not allowed to have empty key paths."); } - realmCore.buildAndVerifyKeyPath(realmObject, keyPaths); + // throw early if the key paths are invalid + realmObject.handle.buildAndVerifyKeyPath(keyPaths); } } From 7725757a41fb929eec453ea8ddb5d6ba9acbe1f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Tue, 23 Apr 2024 16:21:15 +0200 Subject: [PATCH 36/68] Organize imports --- packages/realm_dart/test/test.dart | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/realm_dart/test/test.dart b/packages/realm_dart/test/test.dart index 025966f11..db470bb24 100644 --- a/packages/realm_dart/test/test.dart +++ b/packages/realm_dart/test/test.dart @@ -7,17 +7,20 @@ import 'dart:ffi'; import 'dart:io'; import 'dart:math'; import 'dart:typed_data'; + import 'package:meta/meta.dart'; import 'package:path/path.dart' as _path; -import 'package:realm_dart/src/logging.dart'; -export 'package:test/test.dart'; import 'package:realm_dart/realm.dart'; -import 'package:realm_dart/src/native/realm_core.dart'; import 'package:realm_dart/src/configuration.dart'; +import 'package:realm_dart/src/logging.dart'; +import 'package:realm_dart/src/native/realm_core.dart'; +import 'package:realm_dart/src/realm_object.dart'; import 'package:test/test.dart'; import 'baas_helper.dart'; +export 'package:test/test.dart'; + export 'baas_helper.dart' show AppName; part 'test.realm.dart'; From b7197a242293e9593ae6ff04f484943e416bb307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Tue, 23 Apr 2024 18:38:00 +0200 Subject: [PATCH 37/68] ResultsHandle stuff --- .../realm_dart/lib/src/native/realm_core.dart | 21 ---------------- .../lib/src/native/results_handle.dart | 24 +++++++++++++++---- packages/realm_dart/lib/src/results.dart | 4 ++-- 3 files changed, 21 insertions(+), 28 deletions(-) diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 4d30deaef..3faab4f0c 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -739,15 +739,6 @@ class _RealmCore { }); } - Object? resultsGetElementAt(RealmResults results, int index) { - return using((Arena arena) { - final realm_value = arena(); - invokeGetBool(() => realmLib.realm_results_get(results.handle.pointer, index, realm_value)); - return realm_value.toDartValue(results.realm, () => realmLib.realm_results_get_list(results.handle.pointer, index), - () => realmLib.realm_results_get_dictionary(results.handle.pointer, index)); - }); - } - CollectionChanges getCollectionChanges(RealmCollectionChangesHandle changes) { return using((arena) { final out_num_deletions = arena(); @@ -876,18 +867,6 @@ class _RealmCore { return hashCode; } - RealmNotificationTokenHandle subscribeResultsNotifications(RealmResults results, NotificationsController controller) { - final pointer = invokeGetPointer(() => realmLib.realm_results_add_notification_callback( - results.handle.pointer, - controller.toPersistentHandle(), - realmLib.addresses.realm_dart_delete_persistent_handle, - nullptr, - Pointer.fromFunction(collection_change_callback), - )); - - return RealmNotificationTokenHandle._(pointer, results.realm.handle); - } - UserNotificationTokenHandle subscribeUserNotifications(UserNotificationsController controller) { final callback = Pointer.fromFunction(user_change_callback); final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); diff --git a/packages/realm_dart/lib/src/native/results_handle.dart b/packages/realm_dart/lib/src/native/results_handle.dart index 27c41a8ec..f52a53135 100644 --- a/packages/realm_dart/lib/src/native/results_handle.dart +++ b/packages/realm_dart/lib/src/native/results_handle.dart @@ -81,14 +81,28 @@ class ResultsHandle extends RootedHandleBase { return ResultsHandle._(ptr, realmHandle); } -/* - Object? resultsGetElementAt(int index) { + Object? elementAt(Realm realm, int index) { return using((Arena arena) { final realmValue = arena(); invokeGetBool(() => realmLib.realm_results_get(pointer, index, realmValue)); - return realmValue.toDartValue(results.realm, () => realmLib.realm_results_get_list(pointer, index), - () => realmLib.realm_results_get_dictionary(pointer, index)); + return realmValue.toDartValue( + realm, + () => realmLib.realm_results_get_list(pointer, index), + () => realmLib.realm_results_get_dictionary(pointer, index), + ); }); } -*/ + + RealmNotificationTokenHandle subscribeForNotifications(NotificationsController controller) { + final ptr = invokeGetPointer( + () => realmLib.realm_results_add_notification_callback( + pointer, + controller.toPersistentHandle(), + realmLib.addresses.realm_dart_delete_persistent_handle, + nullptr, + Pointer.fromFunction(collection_change_callback), + ), + ); + return RealmNotificationTokenHandle._(ptr, _root); + } } diff --git a/packages/realm_dart/lib/src/results.dart b/packages/realm_dart/lib/src/results.dart index 5987a6bd2..a2a3f2cc4 100644 --- a/packages/realm_dart/lib/src/results.dart +++ b/packages/realm_dart/lib/src/results.dart @@ -42,7 +42,7 @@ class RealmResults extends Iterable with RealmEntity imple throw RangeError.range(index, 0, length - 1); } - var value = realmCore.resultsGetElementAt(this, _skipOffset + index); + var value = handle.elementAt(realm, _skipOffset + index); if (value is ObjectHandle) { late RealmObjectMetadata targetMetadata; @@ -314,7 +314,7 @@ class ResultsNotificationsController extends NotificationsCon @override RealmNotificationTokenHandle subscribe() { - return realmCore.subscribeResultsNotifications(results, this); + return results.handle.subscribeForNotifications(this); } Stream> createStream() { From b914d0e2196377620f8620bfdd64c0532e7f383b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Tue, 23 Apr 2024 18:45:10 +0200 Subject: [PATCH 38/68] More UserHandle stuff --- packages/realm_dart/lib/src/native/realm_core.dart | 12 ------------ packages/realm_dart/lib/src/native/user_handle.dart | 12 ++++++++++++ packages/realm_dart/lib/src/user.dart | 2 +- packages/realm_dart/test/test.dart | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 3faab4f0c..4576cff1a 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -867,18 +867,6 @@ class _RealmCore { return hashCode; } - UserNotificationTokenHandle subscribeUserNotifications(UserNotificationsController controller) { - final callback = Pointer.fromFunction(user_change_callback); - final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); - final notification_token = realmLib.realm_sync_user_on_state_change_register_callback( - controller.user.handle.pointer, - realmLib.addresses.realm_dart_user_change_callback, - userdata.cast(), - realmLib.addresses.realm_dart_userdata_async_free, - ); - return UserNotificationTokenHandle._(notification_token); - } - RealmCallbackTokenHandle subscribeForSchemaNotifications(Realm realm) { final pointer = invokeGetPointer(() => realmLib.realm_add_schema_changed_callback(realm.handle.pointer, Pointer.fromFunction(schema_change_callback), realm.toPersistentHandle(), realmLib.addresses.realm_dart_delete_persistent_handle)); diff --git a/packages/realm_dart/lib/src/native/user_handle.dart b/packages/realm_dart/lib/src/native/user_handle.dart index 4457d3b18..045156574 100644 --- a/packages/realm_dart/lib/src/native/user_handle.dart +++ b/packages/realm_dart/lib/src/native/user_handle.dart @@ -208,4 +208,16 @@ class UserHandle extends HandleBase { return completer.future; }); } + + UserNotificationTokenHandle subscribeForNotifications(UserNotificationsController controller) { + final callback = Pointer.fromFunction(user_change_callback); + final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); + final notificationToken = realmLib.realm_sync_user_on_state_change_register_callback( + pointer, + realmLib.addresses.realm_dart_user_change_callback, + userdata.cast(), + realmLib.addresses.realm_dart_userdata_async_free, + ); + return UserNotificationTokenHandle._(notificationToken); + } } diff --git a/packages/realm_dart/lib/src/user.dart b/packages/realm_dart/lib/src/user.dart index bcdfa8148..e186a7b13 100644 --- a/packages/realm_dart/lib/src/user.dart +++ b/packages/realm_dart/lib/src/user.dart @@ -170,7 +170,7 @@ class UserNotificationsController implements Finalizable { throw RealmStateError("User notifications subscription already started"); } - tokenHandle = realmCore.subscribeUserNotifications(this); + tokenHandle = user.handle.subscribeForNotifications(this); } void stop() { diff --git a/packages/realm_dart/test/test.dart b/packages/realm_dart/test/test.dart index db470bb24..9d34fcf9a 100644 --- a/packages/realm_dart/test/test.dart +++ b/packages/realm_dart/test/test.dart @@ -676,7 +676,7 @@ Future waitForConditionWithResult(FutureOr Function() getter, FutureOr< } extension RealmObjectTest on RealmObjectBase { - String toJson() => this.handle.objectToString(); + String toJson() => handle.objectToString(); } extension on int { From 59fbdef54194fd5be840d6895b2149580ab45eba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Tue, 23 Apr 2024 19:09:35 +0200 Subject: [PATCH 39/68] subscribeForSchemaNotification (something rubs me the wrong way about this) --- packages/realm_dart/lib/src/native/realm_core.dart | 11 ----------- packages/realm_dart/lib/src/native/realm_handle.dart | 12 ++++++++++++ packages/realm_dart/lib/src/native/user_handle.dart | 4 ++++ packages/realm_dart/lib/src/realm_class.dart | 2 +- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 4576cff1a..7bda125a7 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -867,13 +867,6 @@ class _RealmCore { return hashCode; } - RealmCallbackTokenHandle subscribeForSchemaNotifications(Realm realm) { - final pointer = invokeGetPointer(() => realmLib.realm_add_schema_changed_callback(realm.handle.pointer, Pointer.fromFunction(schema_change_callback), - realm.toPersistentHandle(), realmLib.addresses.realm_dart_delete_persistent_handle)); - - return RealmCallbackTokenHandle._(pointer, realm.handle); - } - bool getObjectChangesIsDeleted(RealmObjectChangesHandle handle) { return realmLib.realm_object_changes_is_deleted(handle.pointer); } @@ -1095,10 +1088,6 @@ class RealmNotificationTokenHandle extends RootedHandleBase pointer, RealmHandle root) : super(root, pointer, 32); } -class UserNotificationTokenHandle extends HandleBase { - UserNotificationTokenHandle._(Pointer pointer) : super(pointer, 32); -} - class RealmSyncSessionConnectionStateNotificationTokenHandle extends HandleBase { RealmSyncSessionConnectionStateNotificationTokenHandle._(Pointer pointer) : super(pointer, 32); } diff --git a/packages/realm_dart/lib/src/native/realm_handle.dart b/packages/realm_dart/lib/src/native/realm_handle.dart index 058d6f715..7d5c0b4be 100644 --- a/packages/realm_dart/lib/src/native/realm_handle.dart +++ b/packages/realm_dart/lib/src/native/realm_handle.dart @@ -283,4 +283,16 @@ class RealmHandle extends HandleBase { return tableDeleted.value; }); } + + RealmCallbackTokenHandle subscribeForSchemaNotifications(Realm realm) { + final ptr = invokeGetPointer( + () => realmLib.realm_add_schema_changed_callback( + pointer, + Pointer.fromFunction(schema_change_callback), + realm.toPersistentHandle(), + realmLib.addresses.realm_dart_delete_persistent_handle, + ), + ); + return RealmCallbackTokenHandle._(ptr, this); + } } diff --git a/packages/realm_dart/lib/src/native/user_handle.dart b/packages/realm_dart/lib/src/native/user_handle.dart index 045156574..27f0bebf3 100644 --- a/packages/realm_dart/lib/src/native/user_handle.dart +++ b/packages/realm_dart/lib/src/native/user_handle.dart @@ -221,3 +221,7 @@ class UserHandle extends HandleBase { return UserNotificationTokenHandle._(notificationToken); } } + +class UserNotificationTokenHandle extends HandleBase { + UserNotificationTokenHandle._(Pointer pointer) : super(pointer, 32); +} diff --git a/packages/realm_dart/lib/src/realm_class.dart b/packages/realm_dart/lib/src/realm_class.dart index 5791db194..43d1b8e6b 100644 --- a/packages/realm_dart/lib/src/realm_class.dart +++ b/packages/realm_dart/lib/src/realm_class.dart @@ -141,7 +141,7 @@ class Realm implements Finalizable { // schema, so even if we subscribe, we wouldn't be able to see the updates. if (config is FlexibleSyncConfiguration || config.schemaObjects.isEmpty) { // TODO: enable once https://github.com/realm/realm-core/issues/7426 is fixed. - // _schemaCallbackHandle = realmCore.subscribeForSchemaNotifications(this); + //_schemaCallbackHandle = handle!.subscribeForSchemaNotifications(this); _schemaCallbackHandle = null; } else { _schemaCallbackHandle = null; From 72322d93912db8030e6ba9dcc27cd2d7a2476151 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Tue, 23 Apr 2024 19:18:15 +0200 Subject: [PATCH 40/68] Move MapHandle.query --- packages/realm_dart/lib/src/map.dart | 2 +- .../realm_dart/lib/src/native/map_handle.dart | 22 ++++++++++++++++ .../realm_dart/lib/src/native/realm_core.dart | 25 ------------------- 3 files changed, 23 insertions(+), 26 deletions(-) diff --git a/packages/realm_dart/lib/src/map.dart b/packages/realm_dart/lib/src/map.dart index b27e766b5..7fb9b247f 100644 --- a/packages/realm_dart/lib/src/map.dart +++ b/packages/realm_dart/lib/src/map.dart @@ -221,7 +221,7 @@ extension RealmMapOfObject on RealmMap { /// /// For more details about the syntax of the Realm Query Language, refer to the documentation: https://www.mongodb.com/docs/realm/realm-query-language/. RealmResults query(String query, [List arguments = const []]) { - final handle = realmCore.queryMap(asManaged(), query, arguments); + final handle = asManaged().handle.query(query, arguments); return RealmResultsInternal.create(handle, realm, metadata); } } diff --git a/packages/realm_dart/lib/src/native/map_handle.dart b/packages/realm_dart/lib/src/native/map_handle.dart index 058a4471b..11e71bd35 100644 --- a/packages/realm_dart/lib/src/native/map_handle.dart +++ b/packages/realm_dart/lib/src/native/map_handle.dart @@ -120,6 +120,28 @@ class MapHandle extends CollectionHandleBase { }); } + ResultsHandle query(String query, List args) { + return using((arena) { + final length = args.length; + final argsPointer = arena(length); + for (var i = 0; i < length; ++i) { + _intoRealmQueryArg(args[i], argsPointer + i, arena); + } + + final queryHandle = QueryHandle._( + invokeGetPointer( + () => realmLib.realm_query_parse_for_results( + values.pointer, + query.toCharPtr(arena), + length, + argsPointer, + ), + ), + _root); + return queryHandle.findAll(); + }); + } + RealmNotificationTokenHandle subscribeForNotifications(NotificationsController controller) { final ptr = invokeGetPointer(() => realmLib.realm_dictionary_add_notification_callback( pointer, diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 7bda125a7..d4b692073 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -1,8 +1,6 @@ // Copyright 2021 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -// ignore_for_file: non_constant_identifier_names - import 'dart:async'; import 'dart:convert'; import 'dart:ffi'; @@ -716,29 +714,6 @@ class _RealmCore { // ignore: unused_element int get _threadId => realmLib.realm_dart_get_thread_id(); - ResultsHandle queryMap(ManagedRealmMap target, String query, List args) { - return using((arena) { - final length = args.length; - final argsPointer = arena(length); - for (var i = 0; i < length; ++i) { - _intoRealmQueryArg(args[i], argsPointer.elementAt(i), arena); - } - - final results = target.handle.values; - final queryHandle = QueryHandle._( - invokeGetPointer( - () => realmLib.realm_query_parse_for_results( - results.pointer, - query.toCharPtr(arena), - length, - argsPointer, - ), - ), - target.realm.handle); - return queryHandle.findAll(); - }); - } - CollectionChanges getCollectionChanges(RealmCollectionChangesHandle changes) { return using((arena) { final out_num_deletions = arena(); From f0e3ee3d6b6cd86e29f071e1be3fa772b12ba4a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Tue, 23 Apr 2024 19:30:51 +0200 Subject: [PATCH 41/68] More ObjectHandle stuff --- .../lib/src/native/object_handle.dart | 14 ++++++++++++++ .../realm_dart/lib/src/native/realm_core.dart | 19 +------------------ .../lib/src/native/realm_handle.dart | 5 +++++ packages/realm_dart/lib/src/realm_object.dart | 4 ++-- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/packages/realm_dart/lib/src/native/object_handle.dart b/packages/realm_dart/lib/src/native/object_handle.dart index 01465a533..0944952e3 100644 --- a/packages/realm_dart/lib/src/native/object_handle.dart +++ b/packages/realm_dart/lib/src/native/object_handle.dart @@ -11,6 +11,20 @@ class ObjectHandle extends RootedHandleBase { return ObjectHandle._(objectPtr, _root); } + (ObjectHandle, int) get parent { + return using((Arena arena) { + final parentPtr = arena>(); + final classKeyPtr = arena(); + invokeGetBool(() => realmLib.realm_object_get_parent(pointer, parentPtr, classKeyPtr)); + + final handle = ObjectHandle._(parentPtr.value, _root); + + return (handle, classKeyPtr.value); + }); + } + + + int get classKey => realmLib.realm_object_get_table(pointer); bool get isValid => realmLib.realm_object_is_valid(pointer); diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index d4b692073..fc9d31073 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -698,18 +698,6 @@ class _RealmCore { return result; } - (ObjectHandle, int) getEmbeddedParent(EmbeddedObject obj) { - return using((Arena arena) { - final parentPtr = arena>(); - final classKeyPtr = arena(); - invokeGetBool(() => realmLib.realm_object_get_parent(obj.handle.pointer, parentPtr, classKeyPtr)); - - final handle = ObjectHandle._(parentPtr.value, obj.realm.handle); - - return (handle, classKeyPtr.value); - }); - } - // For debugging // ignore: unused_element int get _threadId => realmLib.realm_dart_get_thread_id(); @@ -820,11 +808,6 @@ class _RealmCore { return _RealmLinkHandle._(realmLink); } - ObjectHandle _getObject(Realm realm, int classKey, int objectKey) { - final pointer = invokeGetPointer(() => realmLib.realm_get_object(realm.handle.pointer, classKey, objectKey)); - return ObjectHandle._(pointer, realm.handle); - } - bool _equals(HandleBase first, HandleBase second) { return realmLib.realm_equals(first.pointer.cast(), second.pointer.cast()); } @@ -1261,7 +1244,7 @@ extension on realm_value_t { final objectKey = values.link.target; final classKey = values.link.target_table; if (realm.metadata.getByClassKeyIfExists(classKey) == null) return null; // temprorary workaround to avoid crash on assertion - return realmCore._getObject(realm, classKey, objectKey); + return realm.handle._getObject(classKey, objectKey); case realm_value_type.RLM_TYPE_BINARY: return Uint8List.fromList(values.binary.data.asTypedList(values.binary.size)); case realm_value_type.RLM_TYPE_TIMESTAMP: diff --git a/packages/realm_dart/lib/src/native/realm_handle.dart b/packages/realm_dart/lib/src/native/realm_handle.dart index 7d5c0b4be..b9e15dea2 100644 --- a/packages/realm_dart/lib/src/native/realm_handle.dart +++ b/packages/realm_dart/lib/src/native/realm_handle.dart @@ -284,6 +284,11 @@ class RealmHandle extends HandleBase { }); } + ObjectHandle _getObject(int classKey, int objectKey) { + final ptr = invokeGetPointer(() => realmLib.realm_get_object(pointer, classKey, objectKey)); + return ObjectHandle._(ptr, this); + } + RealmCallbackTokenHandle subscribeForSchemaNotifications(Realm realm) { final ptr = invokeGetPointer( () => realmLib.realm_add_schema_changed_callback( diff --git a/packages/realm_dart/lib/src/realm_object.dart b/packages/realm_dart/lib/src/realm_object.dart index b012f10d1..d868c6178 100644 --- a/packages/realm_dart/lib/src/realm_object.dart +++ b/packages/realm_dart/lib/src/realm_object.dart @@ -636,9 +636,9 @@ extension EmbeddedObjectExtension on EmbeddedObject { return null; } - final (handle, classKey) = realmCore.getEmbeddedParent(this); + final (parentHandle, classKey) = handle.parent; final (type, metadata) = realm.metadata.getByClassKey(classKey); - return realm.createObject(type, handle, metadata); + return realm.createObject(type, parentHandle, metadata); } } From 4e7c73c66fbfcf896851cb0012ab10488305f68b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Tue, 23 Apr 2024 20:01:29 +0200 Subject: [PATCH 42/68] Move callback functions into handle files --- .../lib/src/native/config_handle.dart | 88 ++++++++- .../realm_dart/lib/src/native/map_handle.dart | 24 ++- .../lib/src/native/object_handle.dart | 26 ++- .../realm_dart/lib/src/native/realm_core.dart | 182 ------------------ .../lib/src/native/realm_handle.dart | 13 +- .../lib/src/native/session_handle.dart | 48 +++++ .../lib/src/native/user_handle.dart | 47 +++-- packages/realm_dart/lib/src/session.dart | 8 +- 8 files changed, 222 insertions(+), 214 deletions(-) diff --git a/packages/realm_dart/lib/src/native/config_handle.dart b/packages/realm_dart/lib/src/native/config_handle.dart index e3381463b..ed0cddb13 100644 --- a/packages/realm_dart/lib/src/native/config_handle.dart +++ b/packages/realm_dart/lib/src/native/config_handle.dart @@ -40,7 +40,7 @@ class ConfigHandle extends HandleBase { if (config.initialDataCallback != null) { realmLib.realm_config_set_data_initialization_function( configHandle.pointer, - Pointer.fromFunction(initial_data_callback, false), + Pointer.fromFunction(_initialDataCallback, false), config.toPersistentHandle(), realmLib.addresses.realm_dart_delete_persistent_handle, ); @@ -56,7 +56,7 @@ class ConfigHandle extends HandleBase { if (config.shouldCompactCallback != null) { realmLib.realm_config_set_should_compact_on_launch_function( configHandle.pointer, - Pointer.fromFunction(should_compact_callback, false), + Pointer.fromFunction(_shouldCompactCallback, false), config.toPersistentHandle(), realmLib.addresses.realm_dart_delete_persistent_handle, ); @@ -64,7 +64,7 @@ class ConfigHandle extends HandleBase { if (config.migrationCallback != null) { realmLib.realm_config_set_migration_function( configHandle.pointer, - Pointer.fromFunction(migration_callback, false), + Pointer.fromFunction(_migrationCallback, false), config.toPersistentHandle(), realmLib.addresses.realm_dart_delete_persistent_handle, ); @@ -104,7 +104,7 @@ class ConfigHandle extends HandleBase { if (config.shouldCompactCallback != null) { realmLib.realm_config_set_should_compact_on_launch_function( configHandle.pointer, - Pointer.fromFunction(should_compact_callback, false), + Pointer.fromFunction(_shouldCompactCallback, false), config.toPersistentHandle(), realmLib.addresses.realm_dart_delete_persistent_handle, ); @@ -155,3 +155,83 @@ void _syncAfterResetCallback(Object userdata, Pointer beforeHandle } }, unlockCallbackFunc); } + +bool _shouldCompactCallback(Pointer userdata, int totalSize, int usedSize) { + final config = userdata.toObject(); + + if (config is LocalConfiguration) { + return config.shouldCompactCallback!(totalSize, usedSize); + } else if (config is FlexibleSyncConfiguration) { + return config.shouldCompactCallback!(totalSize, usedSize); + } + + return false; +} + +bool _migrationCallback(Pointer userdata, Pointer oldRealmHandle, Pointer newRealmHandle, Pointer schema) { + final oldHandle = RealmHandle._unowned(oldRealmHandle); + final newHandle = RealmHandle._unowned(newRealmHandle); + try { + final LocalConfiguration config = userdata.toObject(); + + final oldSchemaVersion = realmLib.realm_get_schema_version(oldRealmHandle); + final oldConfig = Configuration.local([], path: config.path, isReadOnly: true, schemaVersion: oldSchemaVersion); + final oldRealm = RealmInternal.getUnowned(oldConfig, oldHandle, isInMigration: true); + + final newRealm = RealmInternal.getUnowned(config, newHandle, isInMigration: true); + + final migration = MigrationInternal.create(RealmInternal.getMigrationRealm(oldRealm), newRealm, SchemaHandle.unowned(schema)); + config.migrationCallback!(migration, oldSchemaVersion); + return true; + } catch (ex) { + realmLib.realm_register_user_code_callback_error(ex.toPersistentHandle()); + } finally { + oldHandle.release(); + newHandle.release(); + } + + return false; +} + +void _syncErrorHandlerCallback(Object userdata, Pointer session, realm_sync_error error) { + final syncConfig = userdata as FlexibleSyncConfiguration; + // TODO: Take the app from the session instead of from syncConfig after fixing issue https://github.com/realm/realm-dart/issues/633 + final syncError = SyncErrorInternal.createSyncError(error.toDart(), app: syncConfig.user.app); + + if (syncError is ClientResetError) { + syncConfig.clientResetHandler.onManualReset?.call(syncError); + return; + } + + syncConfig.syncErrorHandler(syncError); +} + +void _syncBeforeResetCallback(Object userdata, Pointer realmPtr, Pointer unlockCallbackFunc) { + _guardSynchronousCallback(() async { + final syncConfig = userdata as FlexibleSyncConfiguration; + var beforeResetCallback = syncConfig.clientResetHandler.onBeforeReset!; + + final realm = RealmInternal.getUnowned(syncConfig, RealmHandle._unowned(realmPtr)); + try { + await beforeResetCallback(realm); + } finally { + realm.handle.release(); + } + }, unlockCallbackFunc); +} + +bool _initialDataCallback(Pointer userdata, Pointer realmPtr) { + final realmHandle = RealmHandle._unowned(realmPtr); + try { + final LocalConfiguration config = userdata.toObject(); + final realm = RealmInternal.getUnowned(config, realmHandle); + config.initialDataCallback!(realm); + return true; + } catch (ex) { + realmLib.realm_register_user_code_callback_error(ex.toPersistentHandle()); + } finally { + realmHandle.release(); + } + + return false; +} diff --git a/packages/realm_dart/lib/src/native/map_handle.dart b/packages/realm_dart/lib/src/native/map_handle.dart index 11e71bd35..100a8724d 100644 --- a/packages/realm_dart/lib/src/native/map_handle.dart +++ b/packages/realm_dart/lib/src/native/map_handle.dart @@ -148,8 +148,30 @@ class MapHandle extends CollectionHandleBase { controller.toPersistentHandle(), realmLib.addresses.realm_dart_delete_persistent_handle, nullptr, - Pointer.fromFunction(map_change_callback), + Pointer.fromFunction(_mapChangeCallback), )); return RealmNotificationTokenHandle._(ptr, _root); } } + +void _mapChangeCallback(Pointer userdata, Pointer data) { + final NotificationsController controller = userdata.toObject(); + + if (data == nullptr) { + controller.onError(RealmError("Invalid notifications data received")); + return; + } + + try { + final clonedData = realmLib.realm_clone(data.cast()); + if (clonedData == nullptr) { + controller.onError(RealmError("Error while cloning notifications data")); + return; + } + + final changesHandle = RealmMapChangesHandle._(clonedData.cast()); + controller.onChanges(changesHandle); + } catch (e) { + controller.onError(RealmError("Error handling change notifications. Error: $e")); + } +} diff --git a/packages/realm_dart/lib/src/native/object_handle.dart b/packages/realm_dart/lib/src/native/object_handle.dart index 0944952e3..8becf057b 100644 --- a/packages/realm_dart/lib/src/native/object_handle.dart +++ b/packages/realm_dart/lib/src/native/object_handle.dart @@ -23,8 +23,6 @@ class ObjectHandle extends RootedHandleBase { }); } - - int get classKey => realmLib.realm_object_get_table(pointer); bool get isValid => realmLib.realm_object_is_valid(pointer); @@ -111,7 +109,7 @@ class ObjectHandle extends RootedHandleBase { controller.toPersistentHandle(), realmLib.addresses.realm_dart_delete_persistent_handle, kpNative, - Pointer.fromFunction(object_change_callback), + Pointer.fromFunction(_objectChangeCallback), )); return RealmNotificationTokenHandle._(ptr, _root); @@ -136,3 +134,25 @@ class ObjectHandle extends RootedHandleBase { }); } } + +void _objectChangeCallback(Pointer userdata, Pointer data) { + final NotificationsController controller = userdata.toObject(); + + if (data == nullptr) { + controller.onError(RealmError("Invalid notifications data received")); + return; + } + + try { + final clonedData = realmLib.realm_clone(data.cast()); + if (clonedData == nullptr) { + controller.onError(RealmError("Error while cloning notifications data")); + return; + } + + final changesHandle = RealmObjectChangesHandle._(clonedData.cast()); + controller.onChanges(changesHandle); + } catch (e) { + controller.onError(RealmError("Error handling change notifications. Error: $e")); + } +} diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index fc9d31073..81e75c05b 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -152,86 +152,6 @@ void _guardSynchronousCallback(FutureOr Function() callback, Pointer } } -bool should_compact_callback(Pointer userdata, int totalSize, int usedSize) { - final config = userdata.toObject(); - - if (config is LocalConfiguration) { - return config.shouldCompactCallback!(totalSize, usedSize); - } else if (config is FlexibleSyncConfiguration) { - return config.shouldCompactCallback!(totalSize, usedSize); - } - - return false; -} - -bool migration_callback(Pointer userdata, Pointer oldRealmHandle, Pointer newRealmHandle, Pointer schema) { - final oldHandle = RealmHandle._unowned(oldRealmHandle); - final newHandle = RealmHandle._unowned(newRealmHandle); - try { - final LocalConfiguration config = userdata.toObject(); - - final oldSchemaVersion = realmLib.realm_get_schema_version(oldRealmHandle); - final oldConfig = Configuration.local([], path: config.path, isReadOnly: true, schemaVersion: oldSchemaVersion); - final oldRealm = RealmInternal.getUnowned(oldConfig, oldHandle, isInMigration: true); - - final newRealm = RealmInternal.getUnowned(config, newHandle, isInMigration: true); - - final migration = MigrationInternal.create(RealmInternal.getMigrationRealm(oldRealm), newRealm, SchemaHandle.unowned(schema)); - config.migrationCallback!(migration, oldSchemaVersion); - return true; - } catch (ex) { - realmLib.realm_register_user_code_callback_error(ex.toPersistentHandle()); - } finally { - oldHandle.release(); - newHandle.release(); - } - - return false; -} - -void _syncErrorHandlerCallback(Object userdata, Pointer session, realm_sync_error error) { - final syncConfig = userdata as FlexibleSyncConfiguration; - // TODO: Take the app from the session instead of from syncConfig after fixing issue https://github.com/realm/realm-dart/issues/633 - final syncError = SyncErrorInternal.createSyncError(error.toDart(), app: syncConfig.user.app); - - if (syncError is ClientResetError) { - syncConfig.clientResetHandler.onManualReset?.call(syncError); - return; - } - - syncConfig.syncErrorHandler(syncError); -} - -void _syncBeforeResetCallback(Object userdata, Pointer realmHandle, Pointer unlockCallbackFunc) { - _guardSynchronousCallback(() async { - final syncConfig = userdata as FlexibleSyncConfiguration; - var beforeResetCallback = syncConfig.clientResetHandler.onBeforeReset!; - - final realm = RealmInternal.getUnowned(syncConfig, RealmHandle._unowned(realmHandle)); - try { - await beforeResetCallback(realm); - } finally { - realm.handle.release(); - } - }, unlockCallbackFunc); -} - -bool initial_data_callback(Pointer userdata, Pointer realmPtr) { - final realmHandle = RealmHandle._unowned(realmPtr); - try { - final LocalConfiguration config = userdata.toObject(); - final realm = RealmInternal.getUnowned(config, realmHandle); - config.initialDataCallback!(realm); - return true; - } catch (ex) { - realmLib.realm_register_user_code_callback_error(ex.toPersistentHandle()); - } finally { - realmHandle.release(); - } - - return false; -} - Pointer _createAsyncUserCallbackUserdata(Completer completer) { final callback = Pointer.fromFunction< Void Function( @@ -413,65 +333,6 @@ void collection_change_callback(Pointer userdata, Pointer userdata, Pointer data) { - final NotificationsController controller = userdata.toObject(); - - if (data == nullptr) { - controller.onError(RealmError("Invalid notifications data received")); - return; - } - - try { - final clonedData = realmLib.realm_clone(data.cast()); - if (clonedData == nullptr) { - controller.onError(RealmError("Error while cloning notifications data")); - return; - } - - final changesHandle = RealmObjectChangesHandle._(clonedData.cast()); - controller.onChanges(changesHandle); - } catch (e) { - controller.onError(RealmError("Error handling change notifications. Error: $e")); - } -} - -void map_change_callback(Pointer userdata, Pointer data) { - final NotificationsController controller = userdata.toObject(); - - if (data == nullptr) { - controller.onError(RealmError("Invalid notifications data received")); - return; - } - - try { - final clonedData = realmLib.realm_clone(data.cast()); - if (clonedData == nullptr) { - controller.onError(RealmError("Error while cloning notifications data")); - return; - } - - final changesHandle = RealmMapChangesHandle._(clonedData.cast()); - controller.onChanges(changesHandle); - } catch (e) { - controller.onError(RealmError("Error handling change notifications. Error: $e")); - } -} - -void user_change_callback(Object userdata, int data) { - final controller = userdata as UserNotificationsController; - - controller.onUserChanged(); -} - -void schema_change_callback(Pointer userdata, Pointer data) { - final Realm realm = userdata.toObject(); - try { - realm.updateSchema(); - } catch (e) { - Realm.logger.log(LogLevel.error, 'Failed to update Realm schema: $e'); - } -} - // All access to Realm Core functionality goes through this class class _RealmCore { // From realm.h. Currently not exported from the shared library @@ -862,45 +723,6 @@ class _RealmCore { realmLib.realm_clear_cached_apps(); } - RealmSyncSessionConnectionStateNotificationTokenHandle sessionRegisterProgressNotifier( - Session session, ProgressDirection direction, ProgressMode mode, SessionProgressNotificationsController controller) { - final isStreaming = mode == ProgressMode.reportIndefinitely; - final callback = Pointer.fromFunction(_syncProgressCallback); - final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); - final tokenPtr = invokeGetPointer(() => realmLib.realm_sync_session_register_progress_notifier( - session.handle.pointer, - realmLib.addresses.realm_dart_sync_progress_callback, - direction.index, - isStreaming, - userdata.cast(), - realmLib.addresses.realm_dart_userdata_async_free)); - return RealmSyncSessionConnectionStateNotificationTokenHandle._(tokenPtr); - } - - static void _syncProgressCallback(Object userdata, int transferred, int transferable, double estimate) { - final controller = userdata as ProgressNotificationsController; - - controller.onProgress(transferred, transferable); - } - - RealmSyncSessionConnectionStateNotificationTokenHandle sessionRegisterConnectionStateNotifier(Session session, SessionConnectionStateController controller) { - final callback = Pointer.fromFunction(_onConnectionStateChange); - final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); - final notification_token = realmLib.realm_sync_session_register_connection_state_change_callback( - session.handle.pointer, - realmLib.addresses.realm_dart_sync_connection_state_changed_callback, - userdata.cast(), - realmLib.addresses.realm_dart_userdata_async_free, - ); - return RealmSyncSessionConnectionStateNotificationTokenHandle._(notification_token); - } - - static void _onConnectionStateChange(Object userdata, int oldState, int newState) { - final controller = userdata as SessionConnectionStateController; - - controller.onConnectionStateChange(ConnectionState.values[oldState], ConnectionState.values[newState]); - } - String _getAppDirectoryFromPlugin() { assert(isFlutterPlatform); @@ -1046,10 +868,6 @@ class RealmNotificationTokenHandle extends RootedHandleBase pointer, RealmHandle root) : super(root, pointer, 32); } -class RealmSyncSessionConnectionStateNotificationTokenHandle extends HandleBase { - RealmSyncSessionConnectionStateNotificationTokenHandle._(Pointer pointer) : super(pointer, 32); -} - class RealmCollectionChangesHandle extends HandleBase { RealmCollectionChangesHandle._(Pointer pointer) : super(pointer, 256); } diff --git a/packages/realm_dart/lib/src/native/realm_handle.dart b/packages/realm_dart/lib/src/native/realm_handle.dart index b9e15dea2..705583e3f 100644 --- a/packages/realm_dart/lib/src/native/realm_handle.dart +++ b/packages/realm_dart/lib/src/native/realm_handle.dart @@ -87,7 +87,7 @@ class RealmHandle extends HandleBase { final length = args.length; final argsPointer = arena(length); for (var i = 0; i < length; ++i) { - _intoRealmQueryArg(args[i], argsPointer.elementAt(i), arena); + _intoRealmQueryArg(args[i], argsPointer + i, arena); } final queryHandle = QueryHandle._( invokeGetPointer( @@ -293,7 +293,7 @@ class RealmHandle extends HandleBase { final ptr = invokeGetPointer( () => realmLib.realm_add_schema_changed_callback( pointer, - Pointer.fromFunction(schema_change_callback), + Pointer.fromFunction(_schemaChangeCallback), realm.toPersistentHandle(), realmLib.addresses.realm_dart_delete_persistent_handle, ), @@ -301,3 +301,12 @@ class RealmHandle extends HandleBase { return RealmCallbackTokenHandle._(ptr, this); } } + +void _schemaChangeCallback(Pointer userdata, Pointer data) { + final Realm realm = userdata.toObject(); + try { + realm.updateSchema(); + } catch (e) { + Realm.logger.log(LogLevel.error, 'Failed to update Realm schema: $e'); + } +} diff --git a/packages/realm_dart/lib/src/native/session_handle.dart b/packages/realm_dart/lib/src/native/session_handle.dart index 1fe02afcd..fc8f92777 100644 --- a/packages/realm_dart/lib/src/native/session_handle.dart +++ b/packages/realm_dart/lib/src/native/session_handle.dart @@ -91,4 +91,52 @@ class SessionHandle extends RootedHandleBase { completer.complete(); } } + + SyncSessionNotificationTokenHandle subscribeForConnectionStateNotifications(SessionConnectionStateController controller) { + final callback = Pointer.fromFunction(_onConnectionStateChange); + final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); + final ptr = invokeGetPointer( + () => realmLib.realm_sync_session_register_connection_state_change_callback( + pointer, + realmLib.addresses.realm_dart_sync_connection_state_changed_callback, + userdata.cast(), + realmLib.addresses.realm_dart_userdata_async_free, + ), + ); + return SyncSessionNotificationTokenHandle._(ptr); + } + + SyncSessionNotificationTokenHandle subscribeForProgressNotifications( + ProgressDirection direction, + ProgressMode mode, + SessionProgressNotificationsController controller, + ) { + final isStreaming = mode == ProgressMode.reportIndefinitely; + final callback = Pointer.fromFunction(_syncProgressCallback); + final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); + final tokenPtr = invokeGetPointer(() => realmLib.realm_sync_session_register_progress_notifier( + pointer, + realmLib.addresses.realm_dart_sync_progress_callback, + direction.index, + isStreaming, + userdata.cast(), + realmLib.addresses.realm_dart_userdata_async_free)); + return SyncSessionNotificationTokenHandle._(tokenPtr); + } +} + +class SyncSessionNotificationTokenHandle extends HandleBase { + SyncSessionNotificationTokenHandle._(Pointer pointer) : super(pointer, 32); +} + +void _onConnectionStateChange(Object userdata, int oldState, int newState) { + final controller = userdata as SessionConnectionStateController; + + controller.onConnectionStateChange(ConnectionState.values[oldState], ConnectionState.values[newState]); +} + +void _syncProgressCallback(Object userdata, int transferred, int transferable, double estimate) { + final controller = userdata as ProgressNotificationsController; + + controller.onProgress(transferred, transferable); } diff --git a/packages/realm_dart/lib/src/native/user_handle.dart b/packages/realm_dart/lib/src/native/user_handle.dart index 27f0bebf3..6a6e81733 100644 --- a/packages/realm_dart/lib/src/native/user_handle.dart +++ b/packages/realm_dart/lib/src/native/user_handle.dart @@ -179,14 +179,16 @@ class UserHandle extends HandleBase { final completer = Completer(); final nativeId = objectId.toNative(arena); - invokeGetBool(() => realmLib.realm_app_user_apikey_provider_client_disable_apikey( - app.pointer, - pointer, - nativeId.ref, - realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - )); + invokeGetBool( + () => realmLib.realm_app_user_apikey_provider_client_disable_apikey( + app.pointer, + pointer, + nativeId.ref, + realmLib.addresses.realm_dart_void_completion_callback, + _createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ), + ); return completer.future; }); @@ -196,21 +198,24 @@ class UserHandle extends HandleBase { return using((Arena arena) { final completer = Completer(); final nativeId = objectId.toNative(arena); - invokeGetBool(() => realmLib.realm_app_user_apikey_provider_client_enable_apikey( - app.pointer, - pointer, - nativeId.ref, - realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - )); - + + invokeGetBool( + () => realmLib.realm_app_user_apikey_provider_client_enable_apikey( + app.pointer, + pointer, + nativeId.ref, + realmLib.addresses.realm_dart_void_completion_callback, + _createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ), + ); + return completer.future; }); } UserNotificationTokenHandle subscribeForNotifications(UserNotificationsController controller) { - final callback = Pointer.fromFunction(user_change_callback); + final callback = Pointer.fromFunction(_userChangeCallback); final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); final notificationToken = realmLib.realm_sync_user_on_state_change_register_callback( pointer, @@ -225,3 +230,9 @@ class UserHandle extends HandleBase { class UserNotificationTokenHandle extends HandleBase { UserNotificationTokenHandle._(Pointer pointer) : super(pointer, 32); } + +void _userChangeCallback(Object userdata, int data) { + final controller = userdata as UserNotificationsController; + + controller.onUserChanged(); +} diff --git a/packages/realm_dart/lib/src/session.dart b/packages/realm_dart/lib/src/session.dart index ef42609f8..03a0ba488 100644 --- a/packages/realm_dart/lib/src/session.dart +++ b/packages/realm_dart/lib/src/session.dart @@ -131,7 +131,7 @@ class SessionProgressNotificationsController implements ProgressNotificationsCon final ProgressDirection _direction; final ProgressMode _mode; - RealmSyncSessionConnectionStateNotificationTokenHandle? _tokenHandle; + SyncSessionNotificationTokenHandle? _tokenHandle; late final StreamController _streamController; SessionProgressNotificationsController(this._session, this._direction, this._mode); @@ -154,7 +154,7 @@ class SessionProgressNotificationsController implements ProgressNotificationsCon if (_tokenHandle != null) { throw RealmStateError("Session progress subscription already started."); } - _tokenHandle = realmCore.sessionRegisterProgressNotifier(_session, _direction, _mode, this); + _tokenHandle = _session.handle.subscribeForProgressNotifications(_direction, _mode, this); } void _stop() { @@ -167,7 +167,7 @@ class SessionProgressNotificationsController implements ProgressNotificationsCon class SessionConnectionStateController { final Session _session; late final StreamController _streamController; - RealmSyncSessionConnectionStateNotificationTokenHandle? _token; + SyncSessionNotificationTokenHandle? _token; SessionConnectionStateController(this._session); @@ -184,7 +184,7 @@ class SessionConnectionStateController { if (_token != null) { throw RealmStateError("Session connection state subscription already started"); } - _token = realmCore.sessionRegisterConnectionStateNotifier(_session, this); + _token = _session.handle.subscribeForConnectionStateNotifications(this); } void _stop() { From 312f90fba797f195c7dc505b63eb50b7f65c4c77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Tue, 23 Apr 2024 20:12:17 +0200 Subject: [PATCH 43/68] Move resolveX to XHandle.resolveIn --- .../lib/src/native/list_handle.dart | 8 ++++++ .../realm_dart/lib/src/native/map_handle.dart | 8 ++++++ .../realm_dart/lib/src/native/realm_core.dart | 26 ------------------- .../realm_dart/lib/src/native/set_handle.dart | 8 ++++++ packages/realm_dart/lib/src/realm_class.dart | 22 ++++++++-------- 5 files changed, 35 insertions(+), 37 deletions(-) diff --git a/packages/realm_dart/lib/src/native/list_handle.dart b/packages/realm_dart/lib/src/native/list_handle.dart index 6d55fe04b..6b0b862c8 100644 --- a/packages/realm_dart/lib/src/native/list_handle.dart +++ b/packages/realm_dart/lib/src/native/list_handle.dart @@ -65,6 +65,14 @@ class ListHandle extends CollectionHandleBase { }); } + ListHandle? resolveIn(RealmHandle frozenRealm) { + return using((Arena arena) { + final resultPtr = arena>(); + invokeGetBool(() => realmLib.realm_list_resolve_in(pointer, frozenRealm.pointer, resultPtr)); + return resultPtr == nullptr ? null : ListHandle._(resultPtr.value, _root); + }); + } + // TODO: Consider splitting into two methods void addOrUpdateAt(int index, Object? value, bool insert) { using((Arena arena) { diff --git a/packages/realm_dart/lib/src/native/map_handle.dart b/packages/realm_dart/lib/src/native/map_handle.dart index 100a8724d..67c097538 100644 --- a/packages/realm_dart/lib/src/native/map_handle.dart +++ b/packages/realm_dart/lib/src/native/map_handle.dart @@ -142,6 +142,14 @@ class MapHandle extends CollectionHandleBase { }); } + MapHandle? resolveIn(RealmHandle frozenRealm) { + return using((Arena arena) { + final resultPtr = arena>(); + invokeGetBool(() => realmLib.realm_dictionary_resolve_in(pointer, frozenRealm.pointer, resultPtr)); + return resultPtr == nullptr ? null : MapHandle._(resultPtr.value, _root); + }); + } + RealmNotificationTokenHandle subscribeForNotifications(NotificationsController controller) { final ptr = invokeGetPointer(() => realmLib.realm_dictionary_add_notification_callback( pointer, diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 81e75c05b..20b31d2aa 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -764,32 +764,6 @@ class _RealmCore { } } - ResultsHandle resolveResults(RealmResults realmResults, Realm frozenRealm) => realmResults.handle.resolveIn(frozenRealm.handle); - - ListHandle? resolveList(ManagedRealmList list, Realm frozenRealm) { - return using((Arena arena) { - final resultPtr = arena>(); - invokeGetBool(() => realmLib.realm_list_resolve_in(list.handle.pointer, frozenRealm.handle.pointer, resultPtr)); - return resultPtr == nullptr ? null : ListHandle._(resultPtr.value, frozenRealm.handle); - }); - } - - SetHandle? resolveSet(ManagedRealmSet set, Realm frozenRealm) { - return using((Arena arena) { - final resultPtr = arena>(); - invokeGetBool(() => realmLib.realm_set_resolve_in(set.handle.pointer, frozenRealm.handle.pointer, resultPtr)); - return resultPtr == nullptr ? null : SetHandle._(resultPtr.value, frozenRealm.handle); - }); - } - - MapHandle? resolveMap(ManagedRealmMap map, Realm frozenRealm) { - return using((Arena arena) { - final resultPtr = arena>(); - invokeGetBool(() => realmLib.realm_dictionary_resolve_in(map.handle.pointer, frozenRealm.handle.pointer, resultPtr)); - return resultPtr == nullptr ? null : MapHandle._(resultPtr.value, frozenRealm.handle); - }); - } - static void _call_app_function_callback(Pointer userdata, Pointer response, Pointer error) { final Completer completer = userdata.toObject(); diff --git a/packages/realm_dart/lib/src/native/set_handle.dart b/packages/realm_dart/lib/src/native/set_handle.dart index 7a6af0e76..4e380aa1c 100644 --- a/packages/realm_dart/lib/src/native/set_handle.dart +++ b/packages/realm_dart/lib/src/native/set_handle.dart @@ -97,6 +97,14 @@ class SetHandle extends RootedHandleBase { invokeGetBool(() => realmLib.realm_set_remove_all(pointer)); } + SetHandle? resolveIn(RealmHandle frozenRealm) { + return using((Arena arena) { + final resultPtr = arena>(); + invokeGetBool(() => realmLib.realm_set_resolve_in(pointer, frozenRealm.pointer, resultPtr)); + return resultPtr == nullptr ? null : SetHandle._(resultPtr.value, _root); + }); + } + RealmNotificationTokenHandle subscribeForNotifications(NotificationsController controller) { final ptr = invokeGetPointer(() => realmLib.realm_set_add_notification_callback( pointer, diff --git a/packages/realm_dart/lib/src/realm_class.dart b/packages/realm_dart/lib/src/realm_class.dart index 43d1b8e6b..4e7f5c506 100644 --- a/packages/realm_dart/lib/src/realm_class.dart +++ b/packages/realm_dart/lib/src/realm_class.dart @@ -804,35 +804,35 @@ extension RealmInternal on Realm { } RealmList? resolveList(ManagedRealmList list) { - final resultHandle = realmCore.resolveList(list, this); - if (resultHandle == null) { + final newHandle = list.handle.resolveIn(handle); + if (newHandle == null) { return null; } - return createList(resultHandle, list.metadata); + return createList(newHandle, list.metadata); } RealmResults resolveResults(RealmResults results) { - final handle = realmCore.resolveResults(results, this); - return RealmResultsInternal.create(handle, this, results.metadata); + final newHandle = results.handle.resolveIn(handle); + return RealmResultsInternal.create(newHandle, this, results.metadata); } RealmSet? resolveSet(ManagedRealmSet set) { - final handle = realmCore.resolveSet(set, this); - if (handle == null) { + final newHandle = set.handle.resolveIn(handle); + if (newHandle == null) { return null; } - return createSet(handle, set.metadata); + return createSet(newHandle, set.metadata); } RealmMap? resolveMap(ManagedRealmMap map) { - final handle = realmCore.resolveMap(map, this); - if (handle == null) { + final newHandle = map.handle.resolveIn(handle); + if (newHandle == null) { return null; } - return createMap(handle, map.metadata); + return createMap(newHandle, map.metadata); } static MigrationRealm getMigrationRealm(Realm realm) => MigrationRealm._(realm); From b1ebcc566b4bf4324f6ec6fd00c57121eb283e87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Wed, 24 Apr 2024 08:20:21 +0200 Subject: [PATCH 44/68] Make a bunch of function public in prep for getting rid of parts --- .../realm_dart/lib/src/native/app_handle.dart | 28 +++--- .../lib/src/native/config_handle.dart | 4 +- .../lib/src/native/list_handle.dart | 10 +- .../realm_dart/lib/src/native/map_handle.dart | 20 ++-- .../lib/src/native/object_handle.dart | 4 +- .../realm_dart/lib/src/native/realm_core.dart | 98 +++++++++---------- .../lib/src/native/realm_handle.dart | 8 +- .../lib/src/native/results_handle.dart | 6 +- .../realm_dart/lib/src/native/set_handle.dart | 10 +- .../lib/src/native/user_handle.dart | 14 +-- 10 files changed, 101 insertions(+), 101 deletions(-) diff --git a/packages/realm_dart/lib/src/native/app_handle.dart b/packages/realm_dart/lib/src/native/app_handle.dart index e8a624591..fa3d077c6 100644 --- a/packages/realm_dart/lib/src/native/app_handle.dart +++ b/packages/realm_dart/lib/src/native/app_handle.dart @@ -53,7 +53,7 @@ class AppHandle extends HandleBase { pointer, user.pointer, realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), + createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ), "Remove user failed", @@ -89,7 +89,7 @@ class AppHandle extends HandleBase { pointer, baseUrl.toString().toCharPtr(arena), realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), + createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ), "Update base URL failed", @@ -105,7 +105,7 @@ class AppHandle extends HandleBase { pointer, user.pointer, realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), + createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ), "Refresh custom data failed", @@ -124,7 +124,7 @@ class AppHandle extends HandleBase { pointer, credentials.handle.pointer, realmLib.addresses.realm_dart_user_completion_callback, - _createAsyncUserCallbackUserdata(completer), + createAsyncUserCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ), "Login failed", @@ -141,7 +141,7 @@ class AppHandle extends HandleBase { email.toCharPtr(arena), password.toRealmString(arena).ref, realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), + createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ), ); @@ -158,7 +158,7 @@ class AppHandle extends HandleBase { token.toCharPtr(arena), tokenId.toCharPtr(arena), realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), + createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ), ); @@ -174,7 +174,7 @@ class AppHandle extends HandleBase { pointer, email.toCharPtr(arena), realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), + createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ), ); @@ -192,7 +192,7 @@ class AppHandle extends HandleBase { token.toCharPtr(arena), tokenId.toCharPtr(arena), realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), + createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ), ); @@ -208,7 +208,7 @@ class AppHandle extends HandleBase { pointer, email.toCharPtr(arena), realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), + createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ), ); @@ -226,7 +226,7 @@ class AppHandle extends HandleBase { password.toRealmString(arena).ref, argsAsJSON != null ? argsAsJSON.toCharPtr(arena) : nullptr, realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), + createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ), ); @@ -242,7 +242,7 @@ class AppHandle extends HandleBase { pointer, email.toCharPtr(arena), realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), + createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ), ); @@ -257,7 +257,7 @@ class AppHandle extends HandleBase { () => realmLib.realm_app_log_out_current_user( pointer, realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), + createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ), "Logout failed", @@ -268,7 +268,7 @@ class AppHandle extends HandleBase { pointer, user.pointer, realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), + createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ), "Logout failed", @@ -284,7 +284,7 @@ class AppHandle extends HandleBase { pointer, user.pointer, realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), + createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ), "Delete user failed", diff --git a/packages/realm_dart/lib/src/native/config_handle.dart b/packages/realm_dart/lib/src/native/config_handle.dart index ed0cddb13..f1c076a17 100644 --- a/packages/realm_dart/lib/src/native/config_handle.dart +++ b/packages/realm_dart/lib/src/native/config_handle.dart @@ -135,7 +135,7 @@ class ConfigHandle extends HandleBase { void _syncAfterResetCallback(Object userdata, Pointer beforeHandle, Pointer afterReference, bool didRecover, Pointer unlockCallbackFunc) { - _guardSynchronousCallback(() async { + guardSynchronousCallback(() async { final syncConfig = userdata as FlexibleSyncConfiguration; final afterResetCallback = didRecover ? syncConfig.clientResetHandler.onAfterRecovery : syncConfig.clientResetHandler.onAfterDiscard; @@ -207,7 +207,7 @@ void _syncErrorHandlerCallback(Object userdata, Pointer sess } void _syncBeforeResetCallback(Object userdata, Pointer realmPtr, Pointer unlockCallbackFunc) { - _guardSynchronousCallback(() async { + guardSynchronousCallback(() async { final syncConfig = userdata as FlexibleSyncConfiguration; var beforeResetCallback = syncConfig.clientResetHandler.onBeforeReset!; diff --git a/packages/realm_dart/lib/src/native/list_handle.dart b/packages/realm_dart/lib/src/native/list_handle.dart index 6b0b862c8..abbc0e2f4 100644 --- a/packages/realm_dart/lib/src/native/list_handle.dart +++ b/packages/realm_dart/lib/src/native/list_handle.dart @@ -39,7 +39,7 @@ class ListHandle extends CollectionHandleBase { final outFound = arena(); // TODO: how should this behave for collections - final realmValue = _toRealmValue(value, arena); + final realmValue = toRealmValue(value, arena); invokeGetBool( () => realmLib.realm_list_find( pointer, @@ -76,14 +76,14 @@ class ListHandle extends CollectionHandleBase { // TODO: Consider splitting into two methods void addOrUpdateAt(int index, Object? value, bool insert) { using((Arena arena) { - final realmValue = _toRealmValue(value, arena); + final realmValue = toRealmValue(value, arena); invokeGetBool(() => (insert ? realmLib.realm_list_insert : realmLib.realm_list_set)(pointer, index, realmValue.ref)); }); } // TODO: avoid taking the [realm] parameter void addOrUpdateCollectionAt(Realm realm, int index, RealmValue value, bool insert) { - _createCollection(realm, value, () => (insert ? realmLib.realm_list_insert_list : realmLib.realm_list_set_list)(pointer, index), + createCollection(realm, value, () => (insert ? realmLib.realm_list_insert_list : realmLib.realm_list_set_list)(pointer, index), () => (insert ? realmLib.realm_list_insert_dictionary : realmLib.realm_list_set_dictionary)(pointer, index)); } @@ -102,7 +102,7 @@ class ListHandle extends CollectionHandleBase { final length = args.length; final argsPointer = arena(length); for (var i = 0; i < length; ++i) { - _intoRealmQueryArg(args[i], argsPointer + i, arena); + intoRealmQueryArg(args[i], argsPointer + i, arena); } final queryHandle = QueryHandle._( invokeGetPointer( @@ -124,7 +124,7 @@ class ListHandle extends CollectionHandleBase { controller.toPersistentHandle(), realmLib.addresses.realm_dart_delete_persistent_handle, nullptr, - Pointer.fromFunction(collection_change_callback), + Pointer.fromFunction(collectionChangeCallback), )); return RealmNotificationTokenHandle._(ptr, _root); } diff --git a/packages/realm_dart/lib/src/native/map_handle.dart b/packages/realm_dart/lib/src/native/map_handle.dart index 67c097538..92d184a62 100644 --- a/packages/realm_dart/lib/src/native/map_handle.dart +++ b/packages/realm_dart/lib/src/native/map_handle.dart @@ -16,7 +16,7 @@ class MapHandle extends CollectionHandleBase { bool remove(String key) { return using((Arena arena) { - final keyNative = _toRealmValue(key, arena); + final keyNative = toRealmValue(key, arena); final outErased = arena(); invokeGetBool(() => realmLib.realm_dictionary_erase(pointer, keyNative.ref, outErased)); return outErased.value; @@ -26,7 +26,7 @@ class MapHandle extends CollectionHandleBase { // TODO: avoid taking the [realm] parameter Object? find(Realm realm, String key) { return using((Arena arena) { - final keyNative = _toRealmValue(key, arena); + final keyNative = toRealmValue(key, arena); final outValue = arena(); final outFound = arena(); invokeGetBool(() => realmLib.realm_dictionary_find(pointer, keyNative.ref, outValue, outFound)); @@ -65,7 +65,7 @@ class MapHandle extends CollectionHandleBase { bool containsKey(String key) { return using((Arena arena) { - final keyNative = _toRealmValue(key, arena); + final keyNative = toRealmValue(key, arena); final found = arena(); invokeGetBool(() => realmLib.realm_dictionary_contains_key(pointer, keyNative.ref, found)); return found.value; @@ -75,7 +75,7 @@ class MapHandle extends CollectionHandleBase { int indexOf(Object? value) { return using((Arena arena) { // TODO: how should this behave for collections - final valueNative = _toRealmValue(value, arena); + final valueNative = toRealmValue(value, arena); final index = arena(); invokeGetBool(() => realmLib.realm_dictionary_contains_value(pointer, valueNative.ref, index)); return index.value; @@ -86,7 +86,7 @@ class MapHandle extends CollectionHandleBase { ObjectHandle insertEmbedded(String key) { return using((Arena arena) { - final keyNative = _toRealmValue(key, arena); + final keyNative = toRealmValue(key, arena); final ptr = invokeGetPointer(() => realmLib.realm_dictionary_insert_embedded(pointer, keyNative.ref)); return ObjectHandle._(ptr, _root); }); @@ -94,8 +94,8 @@ class MapHandle extends CollectionHandleBase { void insert(String key, Object? value) { using((Arena arena) { - final keyNative = _toRealmValue(key, arena); - final valueNative = _toRealmValue(value, arena); + final keyNative = toRealmValue(key, arena); + final valueNative = toRealmValue(value, arena); invokeGetBool( () => realmLib.realm_dictionary_insert( pointer, @@ -110,8 +110,8 @@ class MapHandle extends CollectionHandleBase { void insertCollection(Realm realm, String key, RealmValue value) { using((Arena arena) { - final keyNative = _toRealmValue(key, arena); - _createCollection( + final keyNative = toRealmValue(key, arena); + createCollection( realm, value, () => realmLib.realm_dictionary_insert_list(pointer, keyNative.ref), @@ -125,7 +125,7 @@ class MapHandle extends CollectionHandleBase { final length = args.length; final argsPointer = arena(length); for (var i = 0; i < length; ++i) { - _intoRealmQueryArg(args[i], argsPointer + i, arena); + intoRealmQueryArg(args[i], argsPointer + i, arena); } final queryHandle = QueryHandle._( diff --git a/packages/realm_dart/lib/src/native/object_handle.dart b/packages/realm_dart/lib/src/native/object_handle.dart index 8becf057b..c3284fafa 100644 --- a/packages/realm_dart/lib/src/native/object_handle.dart +++ b/packages/realm_dart/lib/src/native/object_handle.dart @@ -44,7 +44,7 @@ class ObjectHandle extends RootedHandleBase { // with setCollection? void setValue(int propertyKey, Object? value, bool isDefault) { using((Arena arena) { - final realmValue = _toRealmValue(value, arena); + final realmValue = toRealmValue(value, arena); invokeGetBool( () => realmLib.realm_set_value( pointer, @@ -77,7 +77,7 @@ class ObjectHandle extends RootedHandleBase { } void setCollection(Realm realm, int propertyKey, RealmValue value) { - _createCollection( + createCollection( realm, value, () => realmLib.realm_set_list(pointer, propertyKey), diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 20b31d2aa..3b8389588 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -141,7 +141,7 @@ String getBundleId() { return base64Encode(sha256.convert([...salt, ...utf8.encode(bundleId)]).bytes); } -void _guardSynchronousCallback(FutureOr Function() callback, Pointer unlockCallbackFunc) async { +void guardSynchronousCallback(FutureOr Function() callback, Pointer unlockCallbackFunc) async { Pointer user_error = nullptr; try { await callback(); @@ -152,13 +152,13 @@ void _guardSynchronousCallback(FutureOr Function() callback, Pointer } } -Pointer _createAsyncUserCallbackUserdata(Completer completer) { +Pointer createAsyncUserCallbackUserdata(Completer completer) { final callback = Pointer.fromFunction< Void Function( Pointer, Pointer, Pointer, - )>(_app_user_completion_callback); + )>(appUserCompletionCallback); final userdata = realmLib.realm_dart_userdata_async_new( completer, @@ -169,7 +169,7 @@ Pointer _createAsyncUserCallbackUserdata(Completer completer) { return userdata.cast(); } -void _app_api_key_completion_callback(Pointer userdata, Pointer apiKey, Pointer error) { +void appApiKeyCompletionCallback(Pointer userdata, Pointer apiKey, Pointer error) { final Completer completer = userdata.toObject(); if (error != nullptr) { completer.completeWithAppError(error); @@ -178,7 +178,7 @@ void _app_api_key_completion_callback(Pointer userdata, Pointer userdata, Pointer apiKey, int size, Pointer error) { +void appApiKeyArrayCompletionCallback(Pointer userdata, Pointer apiKey, int size, Pointer error) { final Completer> completer = userdata.toObject(); if (error != nullptr) { @@ -194,7 +194,7 @@ void _app_api_key_array_completion_callback(Pointer userdata, Pointer userdata, Pointer user, Pointer error) { +void appUserCompletionCallback(Pointer userdata, Pointer user, Pointer error) { final Completer completer = userdata.toObject(); if (error != nullptr) { @@ -211,7 +211,7 @@ void _app_user_completion_callback(Pointer userdata, Pointer u completer.complete(UserHandle._(user.cast())); } -void _void_completion_callback(Pointer userdata, Pointer error) { +void voidCompletionCallback(Pointer userdata, Pointer error) { final Completer completer = userdata.toObject(); if (error != nullptr) { @@ -222,12 +222,12 @@ void _void_completion_callback(Pointer userdata, Pointer completer.complete(); } -Pointer _createAsyncCallbackUserdata(Completer completer) { +Pointer createAsyncCallbackUserdata(Completer completer) { final callback = Pointer.fromFunction< Void Function( Pointer, Pointer, - )>(_void_completion_callback); + )>(voidCompletionCallback); final userdata = realmLib.realm_dart_userdata_async_new( completer, @@ -238,13 +238,13 @@ Pointer _createAsyncCallbackUserdata(Completer c return userdata.cast(); } -Pointer _createAsyncApikeyCallbackUserdata(Completer completer) { +Pointer createAsyncApikeyCallbackUserdata(Completer completer) { final callback = Pointer.fromFunction< Void Function( Pointer, Pointer, Pointer, - )>(_app_api_key_completion_callback); + )>(appApiKeyCompletionCallback); final userdata = realmLib.realm_dart_userdata_async_new( completer, @@ -255,14 +255,14 @@ Pointer _createAsyncApikeyCallbackUserdata(Completer _createAsyncApikeyListCallbackUserdata(Completer> completer) { +Pointer createAsyncApikeyListCallbackUserdata(Completer> completer) { final callback = Pointer.fromFunction< Void Function( Pointer, Pointer, Size count, Pointer, - )>(_app_api_key_array_completion_callback); + )>(appApiKeyArrayCompletionCallback); final userdata = realmLib.realm_dart_userdata_async_new( completer, @@ -273,7 +273,7 @@ Pointer _createAsyncApikeyListCallbackUserdata(Complet return userdata.cast(); } -void _createCollection(Realm realm, RealmValue value, Pointer Function() createList, Pointer Function() createMap) { +void createCollection(Realm realm, RealmValue value, Pointer Function() createList, Pointer Function() createMap) { CollectionHandleBase? collectionHandle; try { switch (value.collectionType) { @@ -311,7 +311,7 @@ void _createCollection(Realm realm, RealmValue value, Pointer Functi } } -void collection_change_callback(Pointer userdata, Pointer data) { +void collectionChangeCallback(Pointer userdata, Pointer data) { final NotificationsController controller = userdata.toObject(); if (data == nullptr) { @@ -333,6 +333,18 @@ void collection_change_callback(Pointer userdata, Pointer userdata, Pointer response, Pointer error) { + final Completer completer = userdata.toObject(); + + if (error != nullptr) { + completer.completeWithAppError(error); + return; + } + + final stringResponse = response.cast().toRealmDartString()!; + completer.complete(stringResponse); +} + // All access to Realm Core functionality goes through this class class _RealmCore { // From realm.h. Currently not exported from the shared library @@ -391,7 +403,7 @@ class _RealmCore { final completer = CancellableCompleter(cancellationToken); if (!completer.isCancelled) { final callback = - Pointer.fromFunction realm, Pointer error)>(_openRealmAsyncCallback); + Pointer.fromFunction realm, Pointer error)>(openRealmAsyncCallback); final userData = realmLib.realm_dart_userdata_async_new(completer, callback.cast(), scheduler.handle.pointer); realmLib.realm_async_open_task_start( handle.pointer, @@ -403,7 +415,7 @@ class _RealmCore { return completer.future; } - static void _openRealmAsyncCallback(Object userData, Pointer realmSafePtr, Pointer error) { + static void openRealmAsyncCallback(Object userData, Pointer realmSafePtr, Pointer error) { return using((Arena arena) { final completer = userData as CancellableCompleter; if (completer.isCancelled) { @@ -440,14 +452,14 @@ class _RealmCore { RealmSchema readSchema(Realm realm) { return using((Arena arena) { - return _readSchema(realm, arena); + return _readSchema(realm.handle, arena); }); } - RealmSchema _readSchema(Realm realm, Arena arena, {int expectedSize = 10}) { + RealmSchema _readSchema(RealmHandle realm, Arena arena, {int expectedSize = 10}) { final classesPtr = arena(expectedSize); final actualCount = arena(); - invokeGetBool(() => realmLib.realm_get_class_keys(realm.handle.pointer, classesPtr, expectedSize, actualCount)); + invokeGetBool(() => realmLib.realm_get_class_keys(realm.pointer, classesPtr, expectedSize, actualCount)); if (expectedSize < actualCount.value) { arena.free(classesPtr); return _readSchema(realm, arena, expectedSize: actualCount.value); @@ -457,7 +469,7 @@ class _RealmCore { for (var i = 0; i < actualCount.value; i++) { final classInfo = arena(); final classKey = classesPtr.elementAt(i).value; - invokeGetBool(() => realmLib.realm_get_class(realm.handle.pointer, classKey, classInfo)); + invokeGetBool(() => realmLib.realm_get_class(realm.pointer, classKey, classInfo)); final name = classInfo.ref.name.cast().toDartString(); final baseType = ObjectType.values.firstWhere((element) => element.flags == classInfo.ref.flags, @@ -470,10 +482,10 @@ class _RealmCore { return RealmSchema(schemas); } - SchemaObject _getSchemaForClassKey(Realm realm, int classKey, String name, ObjectType baseType, Arena arena, {int expectedSize = 10}) { + SchemaObject _getSchemaForClassKey(RealmHandle realm, int classKey, String name, ObjectType baseType, Arena arena, {int expectedSize = 10}) { final actualCount = arena(); final propertiesPtr = arena(expectedSize); - invokeGetBool(() => realmLib.realm_get_class_properties(realm.handle.pointer, classKey, propertiesPtr, expectedSize, actualCount)); + invokeGetBool(() => realmLib.realm_get_class_properties(realm.pointer, classKey, propertiesPtr, expectedSize, actualCount)); if (expectedSize < actualCount.value) { // The supplied array was too small - resize it @@ -764,25 +776,13 @@ class _RealmCore { } } - static void _call_app_function_callback(Pointer userdata, Pointer response, Pointer error) { - final Completer completer = userdata.toObject(); - - if (error != nullptr) { - completer.completeWithAppError(error); - return; - } - - final stringResponse = response.cast().toRealmDartString()!; - completer.complete(stringResponse); - } - - Pointer _createAsyncFunctionCallbackUserdata(Completer completer) { + Pointer createAsyncFunctionCallbackUserdata(Completer completer) { final callback = Pointer.fromFunction< Void Function( Pointer, Pointer, Pointer, - )>(_call_app_function_callback); + )>(callAppFunctionCallback); final userdata = realmLib.realm_dart_userdata_async_new( completer, @@ -803,7 +803,7 @@ class _RealmCore { argsAsJSON?.toCharPtr(arena) ?? nullptr, nullptr, realmLib.addresses.realm_dart_return_string_callback, - _createAsyncFunctionCallbackUserdata(completer), + createAsyncFunctionCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, )); return completer.future; @@ -892,48 +892,48 @@ extension _StringEx on String { } } -Pointer _toRealmValue(Object? value, Allocator allocator) { +Pointer toRealmValue(Object? value, Allocator allocator) { final realm_value = allocator(); if (value is RealmValue && value.type.isCollection) { throw RealmError( "Don't use _toPrimitiveValue if the value may contain collections. Use storeValue instead. This is a bug in the Realm Flutter SDK and should be reported to https://github.com/realm/realm-dart/issues/new"); } - _intoRealmValue(value, realm_value.ref, allocator); + intoRealmValue(value, realm_value.ref, allocator); return realm_value; } const int _microsecondsPerSecond = 1000 * 1000; const int _nanosecondsPerMicrosecond = 1000; -void _intoRealmQueryArg(Object? value, Pointer realm_query_arg, Allocator allocator) { +void intoRealmQueryArg(Object? value, Pointer realm_query_arg, Allocator allocator) { if (value is Iterable) { realm_query_arg.ref.nb_args = value.length; realm_query_arg.ref.is_list = true; realm_query_arg.ref.arg = allocator(value.length); int i = 0; for (var item in value) { - _intoRealmValue(item, realm_query_arg.ref.arg[i], allocator); + intoRealmValue(item, realm_query_arg.ref.arg[i], allocator); i++; } } else { realm_query_arg.ref.arg = allocator(); realm_query_arg.ref.nb_args = 1; realm_query_arg.ref.is_list = false; - _intoRealmValueHack(value, realm_query_arg.ref.arg.ref, allocator); + intoRealmValueHack(value, realm_query_arg.ref.arg.ref, allocator); } } -void _intoRealmValueHack(Object? value, realm_value realm_value, Allocator allocator) { +void intoRealmValueHack(Object? value, realm_value realm_value, Allocator allocator) { if (value is GeoShape) { - _intoRealmValue(value.toString(), realm_value, allocator); + intoRealmValue(value.toString(), realm_value, allocator); } else if (value is RealmValueType) { - _intoRealmValue(value.toQueryArgString(), realm_value, allocator); + intoRealmValue(value.toQueryArgString(), realm_value, allocator); } else { - _intoRealmValue(value, realm_value, allocator); + intoRealmValue(value, realm_value, allocator); } } -void _intoRealmValue(Object? value, realm_value realm_value, Allocator allocator) { +void intoRealmValue(Object? value, realm_value realm_value, Allocator allocator) { if (value == null) { realm_value.type = realm_value_type.RLM_TYPE_NULL; } else if (value is RealmObjectBase) { @@ -996,7 +996,7 @@ void _intoRealmValue(Object? value, realm_value realm_value, Allocator allocator } else if (value.type == Map) { realm_value.type = realm_value_type.RLM_TYPE_DICTIONARY; } else { - return _intoRealmValue(value.value, realm_value, allocator); + return intoRealmValue(value.value, realm_value, allocator); } } else { throw RealmException("Property type ${value.runtimeType} not supported"); diff --git a/packages/realm_dart/lib/src/native/realm_handle.dart b/packages/realm_dart/lib/src/native/realm_handle.dart index 705583e3f..6a9c93de8 100644 --- a/packages/realm_dart/lib/src/native/realm_handle.dart +++ b/packages/realm_dart/lib/src/native/realm_handle.dart @@ -44,7 +44,7 @@ class RealmHandle extends HandleBase { ObjectHandle createWithPrimaryKey(int classKey, Object? primaryKey) { return using((Arena arena) { - final realmValue = _toRealmValue(primaryKey, arena); + final realmValue = toRealmValue(primaryKey, arena); final realmPtr = invokeGetPointer(() => realmLib.realm_object_create_with_primary_key(pointer, classKey, realmValue.ref)); return ObjectHandle._(realmPtr, this); }); @@ -57,7 +57,7 @@ class RealmHandle extends HandleBase { ObjectHandle getOrCreateWithPrimaryKey(int classKey, Object? primaryKey) { return using((Arena arena) { - final realmValue = _toRealmValue(primaryKey, arena); + final realmValue = toRealmValue(primaryKey, arena); final didCreate = arena(); final realmPtr = invokeGetPointer(() => realmLib.realm_object_get_or_create_with_primary_key( pointer, @@ -87,7 +87,7 @@ class RealmHandle extends HandleBase { final length = args.length; final argsPointer = arena(length); for (var i = 0; i < length; ++i) { - _intoRealmQueryArg(args[i], argsPointer + i, arena); + intoRealmQueryArg(args[i], argsPointer + i, arena); } final queryHandle = QueryHandle._( invokeGetPointer( @@ -254,7 +254,7 @@ class RealmHandle extends HandleBase { ObjectHandle? find(int classKey, Object? primaryKey) { return using((Arena arena) { - final realmValue = _toRealmValue(primaryKey, arena); + final realmValue = toRealmValue(primaryKey, arena); final ptr = realmLib.realm_object_find_with_primary_key(pointer, classKey, realmValue.ref, nullptr); if (ptr == nullptr) { return null; diff --git a/packages/realm_dart/lib/src/native/results_handle.dart b/packages/realm_dart/lib/src/native/results_handle.dart index f52a53135..fe52c07f4 100644 --- a/packages/realm_dart/lib/src/native/results_handle.dart +++ b/packages/realm_dart/lib/src/native/results_handle.dart @@ -11,7 +11,7 @@ class ResultsHandle extends RootedHandleBase { final length = args.length; final argsPointer = arena(length); for (var i = 0; i < length; ++i) { - _intoRealmQueryArg(args[i], argsPointer.elementAt(i), arena); + intoRealmQueryArg(args[i], argsPointer.elementAt(i), arena); } final queryHandle = QueryHandle._( invokeGetPointer( @@ -33,7 +33,7 @@ class ResultsHandle extends RootedHandleBase { final outFound = arena(); // TODO: how should this behave for collections - final realmValue = _toRealmValue(value, arena); + final realmValue = toRealmValue(value, arena); invokeGetBool( () => realmLib.realm_results_find( pointer, @@ -100,7 +100,7 @@ class ResultsHandle extends RootedHandleBase { controller.toPersistentHandle(), realmLib.addresses.realm_dart_delete_persistent_handle, nullptr, - Pointer.fromFunction(collection_change_callback), + Pointer.fromFunction(collectionChangeCallback), ), ); return RealmNotificationTokenHandle._(ptr, _root); diff --git a/packages/realm_dart/lib/src/native/set_handle.dart b/packages/realm_dart/lib/src/native/set_handle.dart index 4e380aa1c..c76600586 100644 --- a/packages/realm_dart/lib/src/native/set_handle.dart +++ b/packages/realm_dart/lib/src/native/set_handle.dart @@ -16,7 +16,7 @@ class SetHandle extends RootedHandleBase { final length = args.length; final argsPointer = arena(length); for (var i = 0; i < length; ++i) { - _intoRealmQueryArg(args[i], argsPointer + i, arena); + intoRealmQueryArg(args[i], argsPointer + i, arena); } final queryHandle = QueryHandle._( invokeGetPointer( @@ -34,7 +34,7 @@ class SetHandle extends RootedHandleBase { bool insert(Object? value) { return using((Arena arena) { - final realmValue = _toRealmValue(value, arena); + final realmValue = toRealmValue(value, arena); final outIndex = arena(); final outInserted = arena(); invokeGetBool(() => realmLib.realm_set_insert(pointer, realmValue.ref, outIndex, outInserted)); @@ -59,7 +59,7 @@ class SetHandle extends RootedHandleBase { bool find(Object? value) { return using((Arena arena) { // TODO: how should this behave for collections - final realmValue = _toRealmValue(value, arena); + final realmValue = toRealmValue(value, arena); final outIndex = arena(); final outFound = arena(); invokeGetBool(() => realmLib.realm_set_find(pointer, realmValue.ref, outIndex, outFound)); @@ -70,7 +70,7 @@ class SetHandle extends RootedHandleBase { bool remove(Object? value) { return using((Arena arena) { // TODO: do we support sets containing mixed collections - final realmValue = _toRealmValue(value, arena); + final realmValue = toRealmValue(value, arena); final outErased = arena(); invokeGetBool(() => realmLib.realm_set_erase(pointer, realmValue.ref, outErased)); return outErased.value; @@ -111,7 +111,7 @@ class SetHandle extends RootedHandleBase { controller.toPersistentHandle(), realmLib.addresses.realm_dart_delete_persistent_handle, nullptr, - Pointer.fromFunction(collection_change_callback), + Pointer.fromFunction(collectionChangeCallback), )); return RealmNotificationTokenHandle._(ptr, _root); } diff --git a/packages/realm_dart/lib/src/native/user_handle.dart b/packages/realm_dart/lib/src/native/user_handle.dart index 6a6e81733..b07838a2c 100644 --- a/packages/realm_dart/lib/src/native/user_handle.dart +++ b/packages/realm_dart/lib/src/native/user_handle.dart @@ -98,7 +98,7 @@ class UserHandle extends HandleBase { pointer, credentials.pointer, realmLib.addresses.realm_dart_user_completion_callback, - _createAsyncUserCallbackUserdata(completer), + createAsyncUserCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ), "Link credentials failed", @@ -116,7 +116,7 @@ class UserHandle extends HandleBase { pointer, namePtr, realmLib.addresses.realm_dart_apikey_callback, - _createAsyncApikeyCallbackUserdata(completer), + createAsyncApikeyCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ), ); @@ -134,7 +134,7 @@ class UserHandle extends HandleBase { pointer, nativeId.ref, realmLib.addresses.realm_dart_apikey_callback, - _createAsyncApikeyCallbackUserdata(completer), + createAsyncApikeyCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, )); @@ -149,7 +149,7 @@ class UserHandle extends HandleBase { app.pointer, pointer, realmLib.addresses.realm_dart_apikey_list_callback, - _createAsyncApikeyListCallbackUserdata(completer), + createAsyncApikeyListCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, )); @@ -166,7 +166,7 @@ class UserHandle extends HandleBase { pointer, nativeId.ref, realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), + createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, )); @@ -185,7 +185,7 @@ class UserHandle extends HandleBase { pointer, nativeId.ref, realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), + createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ), ); @@ -205,7 +205,7 @@ class UserHandle extends HandleBase { pointer, nativeId.ref, realmLib.addresses.realm_dart_void_completion_callback, - _createAsyncCallbackUserdata(completer), + createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ), ); From 95ff222ff5dcca21434e47284da4b8f3a8b427e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Wed, 24 Apr 2024 09:00:32 +0200 Subject: [PATCH 45/68] Refactor XChangesHandle --- packages/realm_dart/lib/src/collections.dart | 6 +- packages/realm_dart/lib/src/list.dart | 2 +- packages/realm_dart/lib/src/map.dart | 11 +- .../src/native/collection_changes_handle.dart | 70 +++++++++++ .../lib/src/native/map_changes_handle.dart | 47 +++++++ .../realm_dart/lib/src/native/map_handle.dart | 2 +- .../realm_dart/lib/src/native/realm_core.dart | 117 +----------------- packages/realm_dart/lib/src/results.dart | 2 +- packages/realm_dart/lib/src/set.dart | 2 +- 9 files changed, 130 insertions(+), 129 deletions(-) create mode 100644 packages/realm_dart/lib/src/native/collection_changes_handle.dart create mode 100644 packages/realm_dart/lib/src/native/map_changes_handle.dart diff --git a/packages/realm_dart/lib/src/collections.dart b/packages/realm_dart/lib/src/collections.dart index d41d450a0..98446811c 100644 --- a/packages/realm_dart/lib/src/collections.dart +++ b/packages/realm_dart/lib/src/collections.dart @@ -47,13 +47,11 @@ class MapChanges { /// Describes the changes in a Realm collection since the last time the notification callback was invoked. class RealmCollectionChanges implements Finalizable { - final RealmCollectionChangesHandle _handle; - CollectionChanges? _values; + final CollectionChangesHandle _handle; + late final CollectionChanges _changes = _handle.changes; RealmCollectionChanges(this._handle); - CollectionChanges get _changes => _values ??= realmCore.getCollectionChanges(_handle); - /// The indexes in the previous version of the collection which have been removed from this one. List get deleted => _changes.deletions; diff --git a/packages/realm_dart/lib/src/list.dart b/packages/realm_dart/lib/src/list.dart index 155f86610..2c5154187 100644 --- a/packages/realm_dart/lib/src/list.dart +++ b/packages/realm_dart/lib/src/list.dart @@ -346,7 +346,7 @@ class ListNotificationsController extends NotificationsContro @override void onChanges(HandleBase changesHandle) { - if (changesHandle is! RealmCollectionChangesHandle) { + if (changesHandle is! CollectionChangesHandle) { throw RealmError("Invalid changes handle. RealmCollectionChangesHandle expected"); } diff --git a/packages/realm_dart/lib/src/map.dart b/packages/realm_dart/lib/src/map.dart index 7fb9b247f..383354ee2 100644 --- a/packages/realm_dart/lib/src/map.dart +++ b/packages/realm_dart/lib/src/map.dart @@ -188,13 +188,10 @@ class ManagedRealmMap with RealmEntity, MapMixin i class RealmMapChanges { /// The collection being monitored for changes. final RealmMap map; + final MapChangesHandle handle; + late final MapChanges _changes = handle.changes; - final RealmMapChangesHandle _handle; - MapChanges? _values; - - RealmMapChanges._(this._handle, this.map); - - MapChanges get _changes => _values ??= realmCore.getMapChanges(_handle); + RealmMapChanges._(this.handle, this.map); /// The keys of the map which have been removed. List get deleted => _changes.deletions; @@ -300,7 +297,7 @@ class MapNotificationsController extends NotificationsControl @override void onChanges(HandleBase changesHandle) { - if (changesHandle is! RealmMapChangesHandle) { + if (changesHandle is! MapChangesHandle) { throw RealmError("Invalid changes handle. RealmMapChangesHandle expected"); } diff --git a/packages/realm_dart/lib/src/native/collection_changes_handle.dart b/packages/realm_dart/lib/src/native/collection_changes_handle.dart new file mode 100644 index 000000000..e747b255a --- /dev/null +++ b/packages/realm_dart/lib/src/native/collection_changes_handle.dart @@ -0,0 +1,70 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + +part of 'realm_core.dart'; + +class CollectionChangesHandle extends HandleBase { + CollectionChangesHandle._(Pointer pointer) : super(pointer, 256); + + CollectionChanges get changes { + return using((arena) { + final outNumDeletions = arena(); + final outNumInsertions = arena(); + final outNumModifications = arena(); + final outNumMoves = arena(); + final outCollectionCleared = arena(); + final outCollectionWasDeleted = arena(); + realmLib.realm_collection_changes_get_num_changes( + pointer, + outNumDeletions, + outNumInsertions, + outNumModifications, + outNumMoves, + outCollectionCleared, + outCollectionWasDeleted, + ); + + final deletionsCount = outNumDeletions != nullptr ? outNumDeletions.value : 0; + final insertionCount = outNumInsertions != nullptr ? outNumInsertions.value : 0; + final modificationCount = outNumModifications != nullptr ? outNumModifications.value : 0; + var moveCount = outNumMoves != nullptr ? outNumMoves.value : 0; + + final outDeletionIndexes = arena(deletionsCount); + final outInsertionIndexes = arena(insertionCount); + final outModificationIndexes = arena(modificationCount); + final outModificationIndexesAfter = arena(modificationCount); + final outMoves = arena(moveCount); + + realmLib.realm_collection_changes_get_changes( + pointer, + outDeletionIndexes, + deletionsCount, + outInsertionIndexes, + insertionCount, + outModificationIndexes, + modificationCount, + outModificationIndexesAfter, + modificationCount, + outMoves, + moveCount, + ); + + var elementZero = outMoves; + List moves = List.filled(moveCount, Move(elementZero.ref.from, elementZero.ref.to)); + for (var i = 1; i < moveCount; i++) { + final movePtr = outMoves + i; + moves[i] = Move(movePtr.ref.from, movePtr.ref.to); + } + + return CollectionChanges( + outDeletionIndexes.toIntList(deletionsCount), + outInsertionIndexes.toIntList(insertionCount), + outModificationIndexes.toIntList(modificationCount), + outModificationIndexesAfter.toIntList(modificationCount), + moves, + outCollectionCleared.value, + outCollectionWasDeleted.value, + ); + }); + } +} diff --git a/packages/realm_dart/lib/src/native/map_changes_handle.dart b/packages/realm_dart/lib/src/native/map_changes_handle.dart new file mode 100644 index 000000000..d2557a5cc --- /dev/null +++ b/packages/realm_dart/lib/src/native/map_changes_handle.dart @@ -0,0 +1,47 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + +part of 'realm_core.dart'; + +class MapChangesHandle extends HandleBase { + MapChangesHandle._(Pointer pointer) : super(pointer, 256); + + MapChanges get changes { + return using((arena) { + final outNumDeletions = arena(); + final outNumInsertions = arena(); + final outNumModifications = arena(); + final outCollectionWasDeleted = arena(); + realmLib.realm_dictionary_get_changes( + pointer, + outNumDeletions, + outNumInsertions, + outNumModifications, + outCollectionWasDeleted, + ); + + final deletionsCount = outNumDeletions != nullptr ? outNumDeletions.value : 0; + final insertionCount = outNumInsertions != nullptr ? outNumInsertions.value : 0; + final modificationCount = outNumModifications != nullptr ? outNumModifications.value : 0; + + final outDeletionIndexes = arena(deletionsCount); + final outInsertionIndexes = arena(insertionCount); + final outModificationIndexes = arena(modificationCount); + final outCollectionWasCleared = arena(); + + realmLib.realm_dictionary_get_changed_keys( + pointer, + outDeletionIndexes, + outNumDeletions, + outInsertionIndexes, + outNumInsertions, + outModificationIndexes, + outNumModifications, + outCollectionWasCleared, + ); + + return MapChanges(outDeletionIndexes.toStringList(deletionsCount), outInsertionIndexes.toStringList(insertionCount), + outModificationIndexes.toStringList(modificationCount), outCollectionWasCleared.value, outCollectionWasDeleted.value); + }); + } +} diff --git a/packages/realm_dart/lib/src/native/map_handle.dart b/packages/realm_dart/lib/src/native/map_handle.dart index 92d184a62..2e836cbe4 100644 --- a/packages/realm_dart/lib/src/native/map_handle.dart +++ b/packages/realm_dart/lib/src/native/map_handle.dart @@ -177,7 +177,7 @@ void _mapChangeCallback(Pointer userdata, Pointer userdata, Pointer realmLib.realm_dart_get_thread_id(); - CollectionChanges getCollectionChanges(RealmCollectionChangesHandle changes) { - return using((arena) { - final out_num_deletions = arena(); - final out_num_insertions = arena(); - final out_num_modifications = arena(); - final out_num_moves = arena(); - final out_collection_cleared = arena(); - final out_collection_was_deleted = arena(); - realmLib.realm_collection_changes_get_num_changes( - changes.pointer, - out_num_deletions, - out_num_insertions, - out_num_modifications, - out_num_moves, - out_collection_cleared, - out_collection_was_deleted, - ); - - final deletionsCount = out_num_deletions != nullptr ? out_num_deletions.value : 0; - final insertionCount = out_num_insertions != nullptr ? out_num_insertions.value : 0; - final modificationCount = out_num_modifications != nullptr ? out_num_modifications.value : 0; - var moveCount = out_num_moves != nullptr ? out_num_moves.value : 0; - - final out_deletion_indexes = arena(deletionsCount); - final out_insertion_indexes = arena(insertionCount); - final out_modification_indexes = arena(modificationCount); - final out_modification_indexes_after = arena(modificationCount); - final out_moves = arena(moveCount); - - realmLib.realm_collection_changes_get_changes( - changes.pointer, - out_deletion_indexes, - deletionsCount, - out_insertion_indexes, - insertionCount, - out_modification_indexes, - modificationCount, - out_modification_indexes_after, - modificationCount, - out_moves, - moveCount, - ); - - var elementZero = out_moves.elementAt(0); - List moves = List.filled(moveCount, Move(elementZero.ref.from, elementZero.ref.to)); - for (var i = 1; i < moveCount; i++) { - final movePtr = out_moves.elementAt(i); - moves[i] = Move(movePtr.ref.from, movePtr.ref.to); - } - - return CollectionChanges( - out_deletion_indexes.toIntList(deletionsCount), - out_insertion_indexes.toIntList(insertionCount), - out_modification_indexes.toIntList(modificationCount), - out_modification_indexes_after.toIntList(modificationCount), - moves, - out_collection_cleared.value, - out_collection_was_deleted.value, - ); - }); - } - - MapChanges getMapChanges(RealmMapChangesHandle changes) { - return using((arena) { - final out_num_deletions = arena(); - final out_num_insertions = arena(); - final out_num_modifications = arena(); - final out_collection_was_deleted = arena(); - realmLib.realm_dictionary_get_changes( - changes.pointer, - out_num_deletions, - out_num_insertions, - out_num_modifications, - out_collection_was_deleted, - ); - - final deletionsCount = out_num_deletions != nullptr ? out_num_deletions.value : 0; - final insertionCount = out_num_insertions != nullptr ? out_num_insertions.value : 0; - final modificationCount = out_num_modifications != nullptr ? out_num_modifications.value : 0; - - final out_deletion_indexes = arena(deletionsCount); - final out_insertion_indexes = arena(insertionCount); - final out_modification_indexes = arena(modificationCount); - final out_collection_was_cleared = arena(); - - realmLib.realm_dictionary_get_changed_keys( - changes.pointer, - out_deletion_indexes, - out_num_deletions, - out_insertion_indexes, - out_num_insertions, - out_modification_indexes, - out_num_modifications, - out_collection_was_cleared, - ); - - return MapChanges(out_deletion_indexes.toStringList(deletionsCount), out_insertion_indexes.toStringList(insertionCount), - out_modification_indexes.toStringList(modificationCount), out_collection_was_cleared.value, out_collection_was_deleted.value); - }); - } - _RealmLinkHandle _getObjectAsLink(RealmObjectBase object) { final realmLink = realmLib.realm_object_as_link(object.handle.pointer); return _RealmLinkHandle._(realmLink); @@ -842,14 +739,6 @@ class RealmNotificationTokenHandle extends RootedHandleBase pointer, RealmHandle root) : super(root, pointer, 32); } -class RealmCollectionChangesHandle extends HandleBase { - RealmCollectionChangesHandle._(Pointer pointer) : super(pointer, 256); -} - -class RealmMapChangesHandle extends HandleBase { - RealmMapChangesHandle._(Pointer pointer) : super(pointer, 256); -} - class RealmObjectChangesHandle extends HandleBase { RealmObjectChangesHandle._(Pointer pointer) : super(pointer, 256); } diff --git a/packages/realm_dart/lib/src/results.dart b/packages/realm_dart/lib/src/results.dart index a2a3f2cc4..3cfdc2ced 100644 --- a/packages/realm_dart/lib/src/results.dart +++ b/packages/realm_dart/lib/src/results.dart @@ -324,7 +324,7 @@ class ResultsNotificationsController extends NotificationsCon @override void onChanges(HandleBase changesHandle) { - if (changesHandle is! RealmCollectionChangesHandle) { + if (changesHandle is! CollectionChangesHandle) { throw RealmError("Invalid changes handle. RealmCollectionChangesHandle expected"); } diff --git a/packages/realm_dart/lib/src/set.dart b/packages/realm_dart/lib/src/set.dart index 3aea3332a..f776bcf4d 100644 --- a/packages/realm_dart/lib/src/set.dart +++ b/packages/realm_dart/lib/src/set.dart @@ -349,7 +349,7 @@ class RealmSetNotificationsController extends NotificationsCo @override void onChanges(HandleBase changesHandle) { - if (changesHandle is! RealmCollectionChangesHandle) { + if (changesHandle is! CollectionChangesHandle) { throw RealmError("Invalid changes handle. RealmCollectionChangesHandle expected"); } From e3e678852ec17d519d8ab79c62b1b9b953d22f24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Wed, 24 Apr 2024 09:30:22 +0200 Subject: [PATCH 46/68] Use CredentialsHandle not Credentils --- packages/realm_dart/lib/src/app.dart | 2 +- packages/realm_dart/lib/src/native/app_handle.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/realm_dart/lib/src/app.dart b/packages/realm_dart/lib/src/app.dart index 0c5fb25c0..28dd6b468 100644 --- a/packages/realm_dart/lib/src/app.dart +++ b/packages/realm_dart/lib/src/app.dart @@ -176,7 +176,7 @@ class App implements Finalizable { /// Logs in a user with the given credentials. Future logIn(Credentials credentials) async { - var userHandle = await handle.logIn(credentials); + var userHandle = await handle.logIn(credentials.handle); return UserInternal.create(userHandle, this); } diff --git a/packages/realm_dart/lib/src/native/app_handle.dart b/packages/realm_dart/lib/src/native/app_handle.dart index fa3d077c6..1797461f7 100644 --- a/packages/realm_dart/lib/src/native/app_handle.dart +++ b/packages/realm_dart/lib/src/native/app_handle.dart @@ -117,12 +117,12 @@ class AppHandle extends HandleBase { return realmLib.realm_app_get_app_id(pointer).cast().toRealmDartString()!; } - Future logIn(Credentials credentials) async { + Future logIn(CredentialsHandle credentials) async { final completer = Completer(); invokeGetBool( () => realmLib.realm_app_log_in_with_credentials( pointer, - credentials.handle.pointer, + credentials.pointer, realmLib.addresses.realm_dart_user_completion_callback, createAsyncUserCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, From 62ed52a0ebb1a849799b014768389acf949a304e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Wed, 24 Apr 2024 09:37:15 +0200 Subject: [PATCH 47/68] Traffic in ResultsHandle not RealmResult + dart fix stuff --- .../mutable_subscription_set_handle.dart | 56 ++++--- .../realm_dart/lib/src/native/realm_core.dart | 146 +++++++++--------- .../lib/src/native/session_handle.dart | 7 + .../src/native/subscription_set_handle.dart | 4 +- .../lib/src/native/user_handle.dart | 2 +- packages/realm_dart/lib/src/session.dart | 4 +- packages/realm_dart/lib/src/subscription.dart | 8 +- 7 files changed, 117 insertions(+), 110 deletions(-) diff --git a/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart b/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart index 3129f1ee2..5bf2687ae 100644 --- a/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart +++ b/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart @@ -10,7 +10,7 @@ class MutableSubscriptionSetHandle extends SubscriptionSetHandle { SubscriptionSetHandle commit() => SubscriptionSetHandle._(invokeGetPointer(() => realmLib.realm_sync_subscription_set_commit(_mutablePointer)), _root); - SubscriptionHandle insertOrAssignSubscription(RealmResults results, String? name, bool update) { + SubscriptionHandle insertOrAssignSubscription(ResultsHandle results, String? name, bool update) { if (!update) { if (name != null && findByName(name) != null) { throw RealmException('Duplicate subscription with name: $name'); @@ -19,13 +19,15 @@ class MutableSubscriptionSetHandle extends SubscriptionSetHandle { return using((arena) { final outIndex = arena(); final outInserted = arena(); - invokeGetBool(() => realmLib.realm_sync_subscription_set_insert_or_assign_results( - _mutablePointer, - results.handle.pointer, - name?.toCharPtr(arena) ?? nullptr, - outIndex, - outInserted, - )); + invokeGetBool( + () => realmLib.realm_sync_subscription_set_insert_or_assign_results( + _mutablePointer, + results.pointer, + name?.toCharPtr(arena) ?? nullptr, + outIndex, + outInserted, + ), + ); return this[outIndex.value]; }); } @@ -33,11 +35,13 @@ class MutableSubscriptionSetHandle extends SubscriptionSetHandle { bool erase(SubscriptionHandle subscription) { return using((arena) { final outErased = arena(); - invokeGetBool(() => realmLib.realm_sync_subscription_set_erase_by_id( - _mutablePointer, - subscription.id.toNative(arena), - outErased, - )); + invokeGetBool( + () => realmLib.realm_sync_subscription_set_erase_by_id( + _mutablePointer, + subscription.id.toNative(arena), + outErased, + ), + ); return outErased.value; }); } @@ -45,23 +49,27 @@ class MutableSubscriptionSetHandle extends SubscriptionSetHandle { bool eraseByName(String name) { return using((arena) { final outErased = arena(); - invokeGetBool(() => realmLib.realm_sync_subscription_set_erase_by_name( - _mutablePointer, - name.toCharPtr(arena), - outErased, - )); + invokeGetBool( + () => realmLib.realm_sync_subscription_set_erase_by_name( + _mutablePointer, + name.toCharPtr(arena), + outErased, + ), + ); return outErased.value; }); } - bool eraseByResults(RealmResults results) { + bool eraseByResults(ResultsHandle results) { return using((arena) { final outErased = arena(); - invokeGetBool(() => realmLib.realm_sync_subscription_set_erase_by_results( - _mutablePointer, - results.handle.pointer, - outErased, - )); + invokeGetBool( + () => realmLib.realm_sync_subscription_set_erase_by_results( + _mutablePointer, + results.pointer, + outErased, + ), + ); return outErased.value; }); } diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index f0e2d1b46..c2bf3db09 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -26,7 +26,6 @@ import '../logging.dart'; import '../migration.dart'; import '../realm_class.dart'; import '../realm_object.dart'; -import '../results.dart'; import '../scheduler.dart'; import '../session.dart'; import '../user.dart'; @@ -140,13 +139,13 @@ String getBundleId() { } void guardSynchronousCallback(FutureOr Function() callback, Pointer unlockCallbackFunc) async { - Pointer user_error = nullptr; + Pointer userError = nullptr; try { await callback(); } catch (error) { - user_error = error.toPersistentHandle(); + userError = error.toPersistentHandle(); } finally { - realmLib.realm_dart_invoke_unlock_callback(user_error, unlockCallbackFunc); + realmLib.realm_dart_invoke_unlock_callback(userError, unlockCallbackFunc); } } @@ -379,13 +378,6 @@ class _RealmCore { // realmLib.realm_dart_gc(); // } - void raiseError(Session session, int errorCode, bool isFatal) { - using((arena) { - final message = "Simulated session error".toCharPtr(arena); - realmLib.realm_sync_session_handle_error_for_testing(session.handle.pointer, errorCode, message, isFatal); - }); - } - void invokeScheduler(int workQueue) { final queuePointer = Pointer.fromAddress(workQueue); realmLib.realm_scheduler_perform_work(queuePointer); @@ -517,8 +509,8 @@ class _RealmCore { void deleteRealmFiles(String path) { using((Arena arena) { - final realm_deleted = arena(); - invokeGetBool(() => realmLib.realm_delete_files(path.toCharPtr(arena), realm_deleted), "Error deleting realm at path $path"); + final realmDeleted = arena(); + invokeGetBool(() => realmLib.realm_delete_files(path.toCharPtr(arena), realmDeleted), "Error deleting realm at path $path"); }); } @@ -603,10 +595,10 @@ class _RealmCore { return using((arena) { final count = realmLib.realm_object_changes_get_num_modified_properties(handle.pointer); - final out_modified = arena(count); - realmLib.realm_object_changes_get_modified_properties(handle.pointer, out_modified, count); + final outModified = arena(count); + realmLib.realm_object_changes_get_modified_properties(handle.pointer, outModified, count); - return out_modified.asTypedList(count).toList(); + return outModified.asTypedList(count).toList(); }); } @@ -622,9 +614,9 @@ class _RealmCore { AppHandle? getApp(String id, String? baseUrl) { return using((arena) { - final out_app = arena>(); - invokeGetBool(() => realmLib.realm_app_get_cached(id.toCharPtr(arena), baseUrl == null ? nullptr : baseUrl.toCharPtr(arena), out_app)); - return out_app.value == nullptr ? null : AppHandle._(out_app.value); + final outApp = arena>(); + invokeGetBool(() => realmLib.realm_app_get_cached(id.toCharPtr(arena), baseUrl == null ? nullptr : baseUrl.toCharPtr(arena), outApp)); + return outApp.value == nullptr ? null : AppHandle._(outApp.value); }); } @@ -716,9 +708,9 @@ class _RealmCore { List getAllCategoryNames() { return using((arena) { final count = realmLib.realm_get_category_names(0, nullptr); - final out_values = arena>(count); - realmLib.realm_get_category_names(count, out_values); - return [for (int i = 0; i < count; i++) out_values[i].cast().toDartString()]; + final outValues = arena>(count); + realmLib.realm_get_category_names(count, outValues); + return [for (int i = 0; i < count; i++) outValues[i].cast().toDartString()]; }); } } @@ -773,94 +765,94 @@ extension _StringEx on String { } Pointer toRealmString(Allocator allocator) { - final realm_string = allocator(); + final realmString = allocator(); final units = utf8.encode(this); - realm_string.ref.data = units.toCharPtr(allocator).cast(); - realm_string.ref.size = units.length; - return realm_string; + realmString.ref.data = units.toCharPtr(allocator).cast(); + realmString.ref.size = units.length; + return realmString; } } Pointer toRealmValue(Object? value, Allocator allocator) { - final realm_value = allocator(); + final realmValue = allocator(); if (value is RealmValue && value.type.isCollection) { throw RealmError( "Don't use _toPrimitiveValue if the value may contain collections. Use storeValue instead. This is a bug in the Realm Flutter SDK and should be reported to https://github.com/realm/realm-dart/issues/new"); } - intoRealmValue(value, realm_value.ref, allocator); - return realm_value; + intoRealmValue(value, realmValue.ref, allocator); + return realmValue; } const int _microsecondsPerSecond = 1000 * 1000; const int _nanosecondsPerMicrosecond = 1000; -void intoRealmQueryArg(Object? value, Pointer realm_query_arg, Allocator allocator) { +void intoRealmQueryArg(Object? value, Pointer realmQueryArg, Allocator allocator) { if (value is Iterable) { - realm_query_arg.ref.nb_args = value.length; - realm_query_arg.ref.is_list = true; - realm_query_arg.ref.arg = allocator(value.length); + realmQueryArg.ref.nb_args = value.length; + realmQueryArg.ref.is_list = true; + realmQueryArg.ref.arg = allocator(value.length); int i = 0; for (var item in value) { - intoRealmValue(item, realm_query_arg.ref.arg[i], allocator); + intoRealmValue(item, realmQueryArg.ref.arg[i], allocator); i++; } } else { - realm_query_arg.ref.arg = allocator(); - realm_query_arg.ref.nb_args = 1; - realm_query_arg.ref.is_list = false; - intoRealmValueHack(value, realm_query_arg.ref.arg.ref, allocator); + realmQueryArg.ref.arg = allocator(); + realmQueryArg.ref.nb_args = 1; + realmQueryArg.ref.is_list = false; + intoRealmValueHack(value, realmQueryArg.ref.arg.ref, allocator); } } -void intoRealmValueHack(Object? value, realm_value realm_value, Allocator allocator) { +void intoRealmValueHack(Object? value, realm_value realmValue, Allocator allocator) { if (value is GeoShape) { - intoRealmValue(value.toString(), realm_value, allocator); + intoRealmValue(value.toString(), realmValue, allocator); } else if (value is RealmValueType) { - intoRealmValue(value.toQueryArgString(), realm_value, allocator); + intoRealmValue(value.toQueryArgString(), realmValue, allocator); } else { - intoRealmValue(value, realm_value, allocator); + intoRealmValue(value, realmValue, allocator); } } -void intoRealmValue(Object? value, realm_value realm_value, Allocator allocator) { +void intoRealmValue(Object? value, realm_value realmValue, Allocator allocator) { if (value == null) { - realm_value.type = realm_value_type.RLM_TYPE_NULL; + realmValue.type = realm_value_type.RLM_TYPE_NULL; } else if (value is RealmObjectBase) { // when converting a RealmObjectBase to realm_value.link we assume the object is managed final link = realmCore._getObjectAsLink(value); - realm_value.values.link.target = link.targetKey; - realm_value.values.link.target_table = link.classKey; - realm_value.type = realm_value_type.RLM_TYPE_LINK; + realmValue.values.link.target = link.targetKey; + realmValue.values.link.target_table = link.classKey; + realmValue.type = realm_value_type.RLM_TYPE_LINK; } else if (value is int) { - realm_value.values.integer = value; - realm_value.type = realm_value_type.RLM_TYPE_INT; + realmValue.values.integer = value; + realmValue.type = realm_value_type.RLM_TYPE_INT; } else if (value is bool) { - realm_value.values.boolean = value; - realm_value.type = realm_value_type.RLM_TYPE_BOOL; + realmValue.values.boolean = value; + realmValue.type = realm_value_type.RLM_TYPE_BOOL; } else if (value is String) { String string = value; final units = utf8.encode(string); final result = allocator(units.length); final Uint8List nativeString = result.asTypedList(units.length); nativeString.setAll(0, units); - realm_value.values.string.data = result.cast(); - realm_value.values.string.size = units.length; - realm_value.type = realm_value_type.RLM_TYPE_STRING; + realmValue.values.string.data = result.cast(); + realmValue.values.string.size = units.length; + realmValue.type = realm_value_type.RLM_TYPE_STRING; } else if (value is double) { - realm_value.values.dnum = value; - realm_value.type = realm_value_type.RLM_TYPE_DOUBLE; + realmValue.values.dnum = value; + realmValue.type = realm_value_type.RLM_TYPE_DOUBLE; } else if (value is ObjectId) { final bytes = value.bytes; for (var i = 0; i < 12; i++) { - realm_value.values.object_id.bytes[i] = bytes[i]; + realmValue.values.object_id.bytes[i] = bytes[i]; } - realm_value.type = realm_value_type.RLM_TYPE_OBJECT_ID; + realmValue.type = realm_value_type.RLM_TYPE_OBJECT_ID; } else if (value is Uuid) { final bytes = value.bytes.asUint8List(); for (var i = 0; i < 16; i++) { - realm_value.values.uuid.bytes[i] = bytes[i]; + realmValue.values.uuid.bytes[i] = bytes[i]; } - realm_value.type = realm_value_type.RLM_TYPE_UUID; + realmValue.type = realm_value_type.RLM_TYPE_UUID; } else if (value is DateTime) { final microseconds = value.toUtc().microsecondsSinceEpoch; final seconds = microseconds ~/ _microsecondsPerSecond; @@ -868,24 +860,24 @@ void intoRealmValue(Object? value, realm_value realm_value, Allocator allocator) if (microseconds < 0 && nanoseconds != 0) { nanoseconds = nanoseconds - _nanosecondsPerMicrosecond * _microsecondsPerSecond; } - realm_value.values.timestamp.seconds = seconds; - realm_value.values.timestamp.nanoseconds = nanoseconds; - realm_value.type = realm_value_type.RLM_TYPE_TIMESTAMP; + realmValue.values.timestamp.seconds = seconds; + realmValue.values.timestamp.nanoseconds = nanoseconds; + realmValue.type = realm_value_type.RLM_TYPE_TIMESTAMP; } else if (value is Decimal128) { - realm_value.values.decimal128 = value.value; - realm_value.type = realm_value_type.RLM_TYPE_DECIMAL128; + realmValue.values.decimal128 = value.value; + realmValue.type = realm_value_type.RLM_TYPE_DECIMAL128; } else if (value is Uint8List) { - realm_value.type = realm_value_type.RLM_TYPE_BINARY; - realm_value.values.binary.size = value.length; - realm_value.values.binary.data = allocator(value.length); - realm_value.values.binary.data.asTypedList(value.length).setAll(0, value); + realmValue.type = realm_value_type.RLM_TYPE_BINARY; + realmValue.values.binary.size = value.length; + realmValue.values.binary.data = allocator(value.length); + realmValue.values.binary.data.asTypedList(value.length).setAll(0, value); } else if (value is RealmValue) { if (value.type == List) { - realm_value.type = realm_value_type.RLM_TYPE_LIST; + realmValue.type = realm_value_type.RLM_TYPE_LIST; } else if (value.type == Map) { - realm_value.type = realm_value_type.RLM_TYPE_DICTIONARY; + realmValue.type = realm_value_type.RLM_TYPE_DICTIONARY; } else { - return intoRealmValue(value.value, realm_value, allocator); + return intoRealmValue(value.value, realmValue, allocator); } } else { throw RealmException("Property type ${value.runtimeType} not supported"); @@ -987,8 +979,8 @@ extension on Pointer { List toStringList(int count) { final result = List.filled(count, ''); for (var i = 0; i < count; i++) { - final str_value = elementAt(i).ref.values.string; - result[i] = str_value.data.cast().toRealmDartString(length: str_value.size)!; + final strValue = elementAt(i).ref.values.string; + result[i] = strValue.data.cast().toRealmDartString(length: strValue.size)!; } return result; @@ -1082,9 +1074,9 @@ extension on Pointer { for (int i = 0; i < length; i++) { final compensatingWrite = this[i]; final reason = compensatingWrite.reason.cast().toDartString(); - final object_name = compensatingWrite.object_name.cast().toDartString(); - final primary_key = compensatingWrite.primary_key.toPrimitiveValue(); - compensatingWrites.add(CompensatingWriteInfo(object_name, reason, RealmValue.from(primary_key))); + final objectName = compensatingWrite.object_name.cast().toDartString(); + final primaryKey = compensatingWrite.primary_key.toPrimitiveValue(); + compensatingWrites.add(CompensatingWriteInfo(objectName, reason, RealmValue.from(primaryKey))); } return compensatingWrites; } diff --git a/packages/realm_dart/lib/src/native/session_handle.dart b/packages/realm_dart/lib/src/native/session_handle.dart index fc8f92777..906f7268d 100644 --- a/packages/realm_dart/lib/src/native/session_handle.dart +++ b/packages/realm_dart/lib/src/native/session_handle.dart @@ -49,6 +49,13 @@ class SessionHandle extends RootedHandleBase { realmLib.realm_sync_session_resume(pointer); } + void raiseError(int errorCode, bool isFatal) { + using((arena) { + final message = "Simulated session error".toCharPtr(arena); + realmLib.realm_sync_session_handle_error_for_testing(pointer, errorCode, message, isFatal); + }); + } + Future waitForUpload([CancellationToken? cancellationToken]) { final completer = CancellableCompleter(cancellationToken); if (!completer.isCancelled) { diff --git a/packages/realm_dart/lib/src/native/subscription_set_handle.dart b/packages/realm_dart/lib/src/native/subscription_set_handle.dart index d330b6248..a184afec5 100644 --- a/packages/realm_dart/lib/src/native/subscription_set_handle.dart +++ b/packages/realm_dart/lib/src/native/subscription_set_handle.dart @@ -31,10 +31,10 @@ class SubscriptionSetHandle extends RootedHandleBase { final result = []; for (var i = 0; i < actualCount.value; i++) { - final identity = identitiesPtr.elementAt(i).ref; + final identity = (identitiesPtr + i).ref; result.add(UserIdentityInternal.create( identity.id.cast().toRealmDartString(freeRealmMemory: true)!, AuthProviderTypeInternal.getByValue(identity.provider_type))); diff --git a/packages/realm_dart/lib/src/session.dart b/packages/realm_dart/lib/src/session.dart index 03a0ba488..d45ea7ecc 100644 --- a/packages/realm_dart/lib/src/session.dart +++ b/packages/realm_dart/lib/src/session.dart @@ -113,9 +113,7 @@ extension SessionInternal on Session { return _handle; } - void raiseError(int errorCode, bool isFatal) { - realmCore.raiseError(this, errorCode, isFatal); - } + void raiseError(int errorCode, bool isFatal) => handle.raiseError(errorCode, isFatal); static SyncProgress createSyncProgress(int transferredBytes, int transferableBytes) => SyncProgress._(progressEstimate: SyncProgress._calculateProgress(transferred: transferredBytes, transferable: transferableBytes)); diff --git a/packages/realm_dart/lib/src/subscription.dart b/packages/realm_dart/lib/src/subscription.dart index ef86b2a91..6ea976f0c 100644 --- a/packages/realm_dart/lib/src/subscription.dart +++ b/packages/realm_dart/lib/src/subscription.dart @@ -4,6 +4,8 @@ import 'dart:core'; import 'dart:ffi'; +import 'package:realm_dart/src/results.dart'; + import 'native/realm_core.dart'; import 'realm_class.dart'; @@ -122,7 +124,7 @@ sealed class SubscriptionSet with Iterable implements Finalizable /// Finds an existing [Subscription] in this set by its query /// /// The [query] is represented by the corresponding [RealmResults] object. - Subscription? find(RealmResults query) => _handle.findByResults(query).convert(Subscription._); + Subscription? find(RealmResults query) => _handle.findByResults(query.handle).convert(Subscription._); /// Finds an existing [Subscription] in this set by name. Subscription? findByName(String name) => _handle.findByName(name).convert(Subscription._); @@ -244,13 +246,13 @@ final class MutableSubscriptionSet extends SubscriptionSet { /// Otherwise a [RealmException] is thrown, in case of duplicates. /// {@category Sync} Subscription add(RealmResults query, {String? name, bool update = false}) => - Subscription._(_handle.insertOrAssignSubscription(query, name, update)); + Subscription._(_handle.insertOrAssignSubscription(query.handle, name, update)); /// Removes the [subscription] from the set, if it exists. bool remove(Subscription subscription) => _handle.erase(subscription._handle); /// Removes the [query] from the set, if it exists. - bool removeByQuery(RealmResults query) => _handle.eraseByResults(query); + bool removeByQuery(RealmResults query) => _handle.eraseByResults(query.handle); /// Removes the subscription from the set that matches by [name], if it exists. bool removeByName(String name) => _handle.eraseByName(name); From cd11777c23b791898749983664a665c5de66947b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Thu, 25 Apr 2024 15:34:22 +0200 Subject: [PATCH 48/68] Split part files --- .vscode/settings.json | 5 +- packages/realm_dart/lib/src/app.dart | 3 +- packages/realm_dart/lib/src/collections.dart | 1 + packages/realm_dart/lib/src/credentials.dart | 3 +- packages/realm_dart/lib/src/list.dart | 3 + packages/realm_dart/lib/src/map.dart | 3 + packages/realm_dart/lib/src/migration.dart | 4 +- .../realm_dart/lib/src/native/app_handle.dart | 65 ++++--- .../src/native/collection_changes_handle.dart | 12 +- .../lib/src/native/config_handle.dart | 37 ++-- .../realm_dart/lib/src/native/convert.dart | 4 +- .../lib/src/native/credentials_handle.dart | 31 ++-- .../realm_dart/lib/src/native/decimal128.dart | 10 +- .../lib/src/native/error_handling.dart | 11 +- .../lib/src/native/list_handle.dart | 31 +++- .../lib/src/native/map_changes_handle.dart | 13 +- .../realm_dart/lib/src/native/map_handle.dart | 34 ++-- .../mutable_subscription_set_handle.dart | 18 +- .../lib/src/native/object_handle.dart | 39 +++-- .../lib/src/native/query_handle.dart | 13 +- .../realm_dart/lib/src/native/realm_core.dart | 164 +++++++----------- .../lib/src/native/realm_handle.dart | 61 ++++--- .../lib/src/native/realm_library.dart | 4 +- .../lib/src/native/results_handle.dart | 30 +++- .../lib/src/native/rooted_handle.dart | 16 +- .../lib/src/native/schema_handle.dart | 34 +++- .../lib/src/native/session_handle.dart | 31 +++- .../realm_dart/lib/src/native/set_handle.dart | 26 ++- .../lib/src/native/subscription_handle.dart | 10 +- .../src/native/subscription_set_handle.dart | 29 +++- .../lib/src/native/user_handle.dart | 33 +++- packages/realm_dart/lib/src/realm_class.dart | 10 +- packages/realm_dart/lib/src/realm_object.dart | 1 + packages/realm_dart/lib/src/results.dart | 3 + packages/realm_dart/lib/src/session.dart | 6 +- packages/realm_dart/lib/src/set.dart | 3 + packages/realm_dart/lib/src/subscription.dart | 8 +- packages/realm_dart/lib/src/user.dart | 1 + packages/realm_dart/test/decimal128_test.dart | 1 + .../realm_dart/test/dynamic_realm_test.dart | 2 - packages/realm_dart/test/embedded_test.dart | 1 + 41 files changed, 537 insertions(+), 277 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 2411f1d50..85ee6879d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -25,6 +25,7 @@ "geospatial", "HRESULT", "keepalive", + "keypaths", "loggable", "maccatalyst", "mugaritz", @@ -167,5 +168,7 @@ "__tuple": "cpp", "__verbose_abort": "cpp" }, - "cmake.sourceDirectory": "${workspaceFolder}/packages/realm_dart" + "cmake.sourceDirectory": "${workspaceFolder}/packages/realm_dart", + "dart.flutterSdkPath": "/Users/kasper/.puro/envs/stable/flutter", + "dart.sdkPath": "/Users/kasper/.puro/envs/stable/flutter/bin/cache/dart-sdk" } \ No newline at end of file diff --git a/packages/realm_dart/lib/src/app.dart b/packages/realm_dart/lib/src/app.dart index 28dd6b468..d7a334335 100644 --- a/packages/realm_dart/lib/src/app.dart +++ b/packages/realm_dart/lib/src/app.dart @@ -12,6 +12,7 @@ import 'package:path/path.dart' as path; import '../realm.dart'; import 'credentials.dart'; import 'logging.dart'; +import 'native/app_handle.dart'; import 'native/realm_core.dart'; import 'user.dart'; @@ -171,7 +172,7 @@ class App implements Finalizable { static AppHandle _createApp(AppConfiguration configuration) { configuration.baseFilePath.createSync(recursive: true); - return AppHandle(configuration); + return AppHandle.from(configuration); } /// Logs in a user with the given credentials. diff --git a/packages/realm_dart/lib/src/collections.dart b/packages/realm_dart/lib/src/collections.dart index 98446811c..47e74ff71 100644 --- a/packages/realm_dart/lib/src/collections.dart +++ b/packages/realm_dart/lib/src/collections.dart @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import 'dart:ffi'; +import 'native/collection_changes_handle.dart'; import 'native/realm_core.dart'; /// Contains index information about objects that moved within the same collection. diff --git a/packages/realm_dart/lib/src/credentials.dart b/packages/realm_dart/lib/src/credentials.dart index 9e09c13d0..14189c169 100644 --- a/packages/realm_dart/lib/src/credentials.dart +++ b/packages/realm_dart/lib/src/credentials.dart @@ -4,8 +4,9 @@ import 'dart:convert'; import 'dart:ffi'; -import 'native/realm_core.dart'; import 'app.dart'; +import 'native/convert.dart'; +import 'native/credentials_handle.dart'; import 'user.dart'; /// An enum containing all authentication providers. These have to be enabled manually for the application before they can be used. diff --git a/packages/realm_dart/lib/src/list.dart b/packages/realm_dart/lib/src/list.dart index 2c5154187..f13e1fe5e 100644 --- a/packages/realm_dart/lib/src/list.dart +++ b/packages/realm_dart/lib/src/list.dart @@ -9,7 +9,10 @@ import 'dart:ffi'; import 'package:collection/collection.dart' as collection; import 'collections.dart'; +import 'native/collection_changes_handle.dart'; import 'native/handle_base.dart'; +import 'native/list_handle.dart'; +import 'native/object_handle.dart'; import 'native/realm_core.dart'; import 'realm_class.dart'; import 'realm_object.dart'; diff --git a/packages/realm_dart/lib/src/map.dart b/packages/realm_dart/lib/src/map.dart index 383354ee2..d9c242f01 100644 --- a/packages/realm_dart/lib/src/map.dart +++ b/packages/realm_dart/lib/src/map.dart @@ -10,6 +10,9 @@ import 'dart:ffi'; import 'collections.dart'; import 'native/handle_base.dart'; +import 'native/map_changes_handle.dart'; +import 'native/map_handle.dart'; +import 'native/object_handle.dart'; import 'native/realm_core.dart'; import 'realm_object.dart'; import 'realm_class.dart'; diff --git a/packages/realm_dart/lib/src/migration.dart b/packages/realm_dart/lib/src/migration.dart index 3b6823cb6..86eaa0d50 100644 --- a/packages/realm_dart/lib/src/migration.dart +++ b/packages/realm_dart/lib/src/migration.dart @@ -1,9 +1,9 @@ // Copyright 2022 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 +import 'native/schema_handle.dart'; import 'realm_class.dart'; -import 'native/realm_core.dart'; -import './realm_object.dart'; +import 'realm_object.dart'; /// A [Migration] object is passed to you when you migrate your database from one version /// to another. It contains the properties for the Realm before and after the migration. diff --git a/packages/realm_dart/lib/src/native/app_handle.dart b/packages/realm_dart/lib/src/native/app_handle.dart index 1797461f7..0f26c5c5d 100644 --- a/packages/realm_dart/lib/src/native/app_handle.dart +++ b/packages/realm_dart/lib/src/native/app_handle.dart @@ -1,13 +1,34 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -part of 'realm_core.dart'; + +import 'dart:async'; +import 'dart:convert'; +import 'dart:ffi'; +import 'dart:io'; +import 'dart:isolate'; + +import 'package:ffi/ffi.dart'; +import 'package:realm_dart/src/native/convert.dart'; + +import '../app.dart'; // TODO: Remove this import +import '../init.dart'; +import '../logging.dart'; +import '../realm_class.dart'; // TODO: Remove this import +import '../scheduler.dart'; +import 'credentials_handle.dart'; +import 'error_handling.dart'; +import 'handle_base.dart'; +import 'realm_bindings.dart'; +import 'realm_core.dart'; // TODO: Remove this import +import 'realm_library.dart'; +import 'user_handle.dart'; class AppHandle extends HandleBase { - AppHandle._(Pointer pointer) : super(pointer, 16); + AppHandle(Pointer pointer) : super(pointer, 16); static bool _firstTime = true; - factory AppHandle(AppConfiguration configuration) { + factory AppHandle.from(AppConfiguration configuration) { // to avoid caching apps across hot restarts we clear the cache on the first // time the ctor is called in the root isolate. if (_firstTime && _isRootIsolate) { @@ -18,11 +39,11 @@ class AppHandle extends HandleBase { final appConfigHandle = _createAppConfig(configuration, httpTransportHandle); final syncClientConfigHandle = _createSyncClientConfig(configuration); final realmAppPtr = invokeGetPointer(() => realmLib.realm_app_create_cached(appConfigHandle.pointer, syncClientConfigHandle.pointer)); - return AppHandle._(realmAppPtr); + return AppHandle(realmAppPtr); } UserHandle? get currentUser { - return realmLib.realm_app_get_current_user(pointer).convert(UserHandle._); + return realmLib.realm_app_get_current_user(pointer).convert(UserHandle.new); } List get users => using((arena) => _getUsers(arena)); @@ -40,7 +61,7 @@ class AppHandle extends HandleBase { final result = []; for (var i = 0; i < actualCount.value; i++) { - result.add(UserHandle._((usersPtr + i).value)); + result.add(UserHandle((usersPtr + i).value)); } return result; @@ -317,13 +338,13 @@ class AppHandle extends HandleBase { final bool _isRootIsolate = Isolate.current.debugName == 'main'; class _HttpTransportHandle extends HandleBase { - _HttpTransportHandle._(Pointer pointer) : super(pointer, 24); + _HttpTransportHandle(Pointer pointer) : super(pointer, 24); } _HttpTransportHandle _createHttpTransport(HttpClient httpClient) { final requestCallback = Pointer.fromFunction)>(_requestCallback); final requestCallbackUserdata = realmLib.realm_dart_userdata_async_new(httpClient, requestCallback.cast(), scheduler.handle.pointer); - return _HttpTransportHandle._(realmLib.realm_http_transport_new( + return _HttpTransportHandle(realmLib.realm_http_transport_new( realmLib.addresses.realm_dart_http_request_callback, requestCallbackUserdata.cast(), realmLib.addresses.realm_dart_userdata_async_free, @@ -371,26 +392,26 @@ Future _requestCallbackAsync( await using((arena) async { final responsePointer = arena(); final responseRef = responsePointer.ref; - final method = _HttpMethod.values[requestMethod]; + final method = HttpMethod.values[requestMethod]; try { // Build request late HttpClientRequest request; switch (method) { - case _HttpMethod.delete: + case HttpMethod.delete: request = await client.deleteUrl(url); break; - case _HttpMethod.put: + case HttpMethod.put: request = await client.putUrl(url); break; - case _HttpMethod.patch: + case HttpMethod.patch: request = await client.patchUrl(url); break; - case _HttpMethod.post: + case HttpMethod.post: request = await client.postUrl(url); break; - case _HttpMethod.get: + case HttpMethod.get: request = await client.getUrl(url); break; } @@ -438,16 +459,16 @@ Future _requestCallbackAsync( } }); - responseRef.custom_status_code = _CustomErrorCode.noError.code; + responseRef.custom_status_code = CustomErrorCode.noError.code; } on SocketException catch (socketEx) { Realm.logger.log(LogLevel.warn, "HTTP Transport: SocketException executing ${method.name} $url: $socketEx"); - responseRef.custom_status_code = _CustomErrorCode.timeout.code; + responseRef.custom_status_code = CustomErrorCode.timeout.code; } on HttpException catch (httpEx) { Realm.logger.log(LogLevel.warn, "HTTP Transport: HttpException executing ${method.name} $url: $httpEx"); - responseRef.custom_status_code = _CustomErrorCode.unknownHttp.code; + responseRef.custom_status_code = CustomErrorCode.unknownHttp.code; } catch (ex) { Realm.logger.log(LogLevel.error, "HTTP Transport: Exception executing ${method.name} $url: $ex"); - responseRef.custom_status_code = _CustomErrorCode.unknown.code; + responseRef.custom_status_code = CustomErrorCode.unknown.code; } finally { realmLib.realm_http_transport_complete_request(requestContext, responsePointer); } @@ -455,12 +476,12 @@ Future _requestCallbackAsync( } class _SyncClientConfigHandle extends HandleBase { - _SyncClientConfigHandle._(Pointer pointer) : super(pointer, 8); + _SyncClientConfigHandle(Pointer pointer) : super(pointer, 8); } _SyncClientConfigHandle _createSyncClientConfig(AppConfiguration configuration) { return using((arena) { - final handle = _SyncClientConfigHandle._(realmLib.realm_sync_client_config_new()); + final handle = _SyncClientConfigHandle(realmLib.realm_sync_client_config_new()); realmLib.realm_sync_client_config_set_base_file_path(handle.pointer, configuration.baseFilePath.path.toCharPtr(arena)); realmLib.realm_sync_client_config_set_metadata_mode(handle.pointer, configuration.metadataPersistenceMode.index); @@ -473,13 +494,13 @@ _SyncClientConfigHandle _createSyncClientConfig(AppConfiguration configuration) } class _AppConfigHandle extends HandleBase { - _AppConfigHandle._(Pointer pointer) : super(pointer, 8); + _AppConfigHandle(Pointer pointer) : super(pointer, 8); } _AppConfigHandle _createAppConfig(AppConfiguration configuration, _HttpTransportHandle httpTransport) { return using((arena) { final appId = configuration.appId.toCharPtr(arena); - final handle = _AppConfigHandle._(realmLib.realm_app_config_new(appId, httpTransport.pointer)); + final handle = _AppConfigHandle(realmLib.realm_app_config_new(appId, httpTransport.pointer)); realmLib.realm_app_config_set_platform_version(handle.pointer, Platform.operatingSystemVersion.toCharPtr(arena)); diff --git a/packages/realm_dart/lib/src/native/collection_changes_handle.dart b/packages/realm_dart/lib/src/native/collection_changes_handle.dart index e747b255a..d5df9a5ec 100644 --- a/packages/realm_dart/lib/src/native/collection_changes_handle.dart +++ b/packages/realm_dart/lib/src/native/collection_changes_handle.dart @@ -1,10 +1,18 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -part of 'realm_core.dart'; +import 'dart:ffi'; + +import 'package:ffi/ffi.dart'; + +import '../collections.dart'; // TODO: Remove this import +import 'handle_base.dart'; +import 'realm_bindings.dart'; +import 'realm_core.dart'; // TODO: Remove this import +import 'realm_library.dart'; class CollectionChangesHandle extends HandleBase { - CollectionChangesHandle._(Pointer pointer) : super(pointer, 256); + CollectionChangesHandle(Pointer pointer) : super(pointer, 256); CollectionChanges get changes { return using((arena) { diff --git a/packages/realm_dart/lib/src/native/config_handle.dart b/packages/realm_dart/lib/src/native/config_handle.dart index f1c076a17..4b7647d81 100644 --- a/packages/realm_dart/lib/src/native/config_handle.dart +++ b/packages/realm_dart/lib/src/native/config_handle.dart @@ -1,18 +1,33 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -part of 'realm_core.dart'; +import 'dart:ffi'; + +import 'package:ffi/ffi.dart'; + +import '../configuration.dart'; // TODO: Remove this import +import '../migration.dart'; // TODO: Remove this import +import '../realm_class.dart'; // TODO: Remove this import +import '../scheduler.dart'; // TODO: Remove this import +import '../user.dart'; // TODO: Remove this import +import 'error_handling.dart'; +import 'handle_base.dart'; +import 'realm_bindings.dart'; +import 'realm_core.dart'; +import 'realm_handle.dart'; +import 'realm_library.dart'; +import 'schema_handle.dart'; // TODO: Remove this import class ConfigHandle extends HandleBase { - ConfigHandle._(Pointer pointer) : super(pointer, 512); + ConfigHandle(Pointer pointer) : super(pointer, 512); - factory ConfigHandle(Configuration config) { + factory ConfigHandle.from(Configuration config) { return using((Arena arena) { final configPtr = realmLib.realm_config_new(); - final configHandle = ConfigHandle._(configPtr); + final configHandle = ConfigHandle(configPtr); if (config.schemaObjects.isNotEmpty) { - final schemaHandle = SchemaHandle(config.schemaObjects); + final schemaHandle = SchemaHandle.from(config.schemaObjects); realmLib.realm_config_set_schema(configHandle.pointer, schemaHandle.pointer); } @@ -143,9 +158,9 @@ void _syncAfterResetCallback(Object userdata, Pointer beforeHandle return; } - final beforeRealm = RealmInternal.getUnowned(syncConfig, RealmHandle._unowned(beforeHandle)); + final beforeRealm = RealmInternal.getUnowned(syncConfig, RealmHandle.unowned(beforeHandle)); final realmPtr = invokeGetPointer(() => realmLib.realm_from_thread_safe_reference(afterReference, scheduler.handle.pointer)); - final afterRealm = RealmInternal.getUnowned(syncConfig, RealmHandle._unowned(realmPtr)); + final afterRealm = RealmInternal.getUnowned(syncConfig, RealmHandle.unowned(realmPtr)); try { return await afterResetCallback(beforeRealm, afterRealm); @@ -169,8 +184,8 @@ bool _shouldCompactCallback(Pointer userdata, int totalSize, int usedSize) } bool _migrationCallback(Pointer userdata, Pointer oldRealmHandle, Pointer newRealmHandle, Pointer schema) { - final oldHandle = RealmHandle._unowned(oldRealmHandle); - final newHandle = RealmHandle._unowned(newRealmHandle); + final oldHandle = RealmHandle.unowned(oldRealmHandle); + final newHandle = RealmHandle.unowned(newRealmHandle); try { final LocalConfiguration config = userdata.toObject(); @@ -211,7 +226,7 @@ void _syncBeforeResetCallback(Object userdata, Pointer realmPtr, P final syncConfig = userdata as FlexibleSyncConfiguration; var beforeResetCallback = syncConfig.clientResetHandler.onBeforeReset!; - final realm = RealmInternal.getUnowned(syncConfig, RealmHandle._unowned(realmPtr)); + final realm = RealmInternal.getUnowned(syncConfig, RealmHandle.unowned(realmPtr)); try { await beforeResetCallback(realm); } finally { @@ -221,7 +236,7 @@ void _syncBeforeResetCallback(Object userdata, Pointer realmPtr, P } bool _initialDataCallback(Pointer userdata, Pointer realmPtr) { - final realmHandle = RealmHandle._unowned(realmPtr); + final realmHandle = RealmHandle.unowned(realmPtr); try { final LocalConfiguration config = userdata.toObject(); final realm = RealmInternal.getUnowned(config, realmHandle); diff --git a/packages/realm_dart/lib/src/native/convert.dart b/packages/realm_dart/lib/src/native/convert.dart index d619c4f9c..34c258b22 100644 --- a/packages/realm_dart/lib/src/native/convert.dart +++ b/packages/realm_dart/lib/src/native/convert.dart @@ -1,7 +1,9 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -part of 'realm_core.dart'; +import 'dart:ffi'; + +import 'handle_base.dart'; extension PointerEx on Pointer { Pointer? get nullPtrAsNull => this == nullptr ? null : this; diff --git a/packages/realm_dart/lib/src/native/credentials_handle.dart b/packages/realm_dart/lib/src/native/credentials_handle.dart index 5bb5e5fba..94e2e1a1f 100644 --- a/packages/realm_dart/lib/src/native/credentials_handle.dart +++ b/packages/realm_dart/lib/src/native/credentials_handle.dart @@ -1,55 +1,64 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -part of 'realm_core.dart'; +import 'dart:ffi'; + +import 'package:ffi/ffi.dart'; + +import '../credentials.dart'; // TODO: Remove this import +import 'error_handling.dart'; +import 'handle_base.dart'; +import 'realm_bindings.dart'; +import 'realm_core.dart'; // TODO: Remove this import +import 'realm_library.dart'; class CredentialsHandle extends HandleBase { - CredentialsHandle._(Pointer pointer) : super(pointer, 16); + CredentialsHandle(Pointer pointer) : super(pointer, 16); factory CredentialsHandle.anonymous(bool reuseCredentials) { - return CredentialsHandle._(realmLib.realm_app_credentials_new_anonymous(reuseCredentials)); + return CredentialsHandle(realmLib.realm_app_credentials_new_anonymous(reuseCredentials)); } factory CredentialsHandle.emailPassword(String email, String password) { return using((arena) { final emailPtr = email.toCharPtr(arena); final passwordPtr = password.toRealmString(arena); - return CredentialsHandle._(realmLib.realm_app_credentials_new_email_password(emailPtr, passwordPtr.ref)); + return CredentialsHandle(realmLib.realm_app_credentials_new_email_password(emailPtr, passwordPtr.ref)); }); } factory CredentialsHandle.jwt(String token) { return using((arena) { final tokenPtr = token.toCharPtr(arena); - return CredentialsHandle._(realmLib.realm_app_credentials_new_jwt(tokenPtr)); + return CredentialsHandle(realmLib.realm_app_credentials_new_jwt(tokenPtr)); }); } factory CredentialsHandle.apple(String idToken) { return using((arena) { final idTokenPtr = idToken.toCharPtr(arena); - return CredentialsHandle._(realmLib.realm_app_credentials_new_apple(idTokenPtr)); + return CredentialsHandle(realmLib.realm_app_credentials_new_apple(idTokenPtr)); }); } factory CredentialsHandle.facebook(String accessToken) { return using((arena) { final accessTokenPtr = accessToken.toCharPtr(arena); - return CredentialsHandle._(realmLib.realm_app_credentials_new_facebook(accessTokenPtr)); + return CredentialsHandle(realmLib.realm_app_credentials_new_facebook(accessTokenPtr)); }); } factory CredentialsHandle.googleIdToken(String idToken) { return using((arena) { final idTokenPtr = idToken.toCharPtr(arena); - return CredentialsHandle._(realmLib.realm_app_credentials_new_google_id_token(idTokenPtr)); + return CredentialsHandle(realmLib.realm_app_credentials_new_google_id_token(idTokenPtr)); }); } factory CredentialsHandle.googleAuthCode(String authCode) { return using((arena) { final authCodePtr = authCode.toCharPtr(arena); - return CredentialsHandle._(realmLib.realm_app_credentials_new_google_auth_code(authCodePtr)); + return CredentialsHandle(realmLib.realm_app_credentials_new_google_auth_code(authCodePtr)); }); } @@ -57,14 +66,14 @@ class CredentialsHandle extends HandleBase { return using((arena) { final payloadPtr = payload.toCharPtr(arena); final credentialsPtr = invokeGetPointer(() => realmLib.realm_app_credentials_new_function(payloadPtr)); - return CredentialsHandle._(credentialsPtr); + return CredentialsHandle(credentialsPtr); }); } factory CredentialsHandle.apiKey(String key) { return using((arena) { final keyPtr = key.toCharPtr(arena); - return CredentialsHandle._(realmLib.realm_app_credentials_new_api_key(keyPtr)); + return CredentialsHandle(realmLib.realm_app_credentials_new_api_key(keyPtr)); }); } diff --git a/packages/realm_dart/lib/src/native/decimal128.dart b/packages/realm_dart/lib/src/native/decimal128.dart index 5c05eb5b8..24fca8d6f 100644 --- a/packages/realm_dart/lib/src/native/decimal128.dart +++ b/packages/realm_dart/lib/src/native/decimal128.dart @@ -1,7 +1,15 @@ // Copyright 2023 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -part of 'realm_core.dart'; +import 'dart:convert'; +import 'dart:ffi'; + +import 'package:ffi/ffi.dart'; +import 'package:realm_common/realm_common.dart' as common; + +import 'realm_bindings.dart'; +import 'realm_core.dart'; // TODO: Remove this import +import 'realm_library.dart'; /// A 128-bit decimal floating point number. class Decimal128 implements Comparable, common.Decimal128 { diff --git a/packages/realm_dart/lib/src/native/error_handling.dart b/packages/realm_dart/lib/src/native/error_handling.dart index f6242d92f..320ff8b4d 100644 --- a/packages/realm_dart/lib/src/native/error_handling.dart +++ b/packages/realm_dart/lib/src/native/error_handling.dart @@ -1,7 +1,14 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -part of 'realm_core.dart'; +import 'dart:ffi'; + +import 'package:ffi/ffi.dart'; + +import '../realm_object.dart'; +import 'realm_bindings.dart'; +import 'realm_core.dart'; +import 'realm_library.dart'; void invokeGetBool(bool Function() callback, [String? errorMessage]) { bool success = callback(); @@ -52,7 +59,7 @@ Never throwLastError([String? errorMessage]) { }); } -extension on realm_error { +extension RealmErrorEx on realm_error { LastError toDart() { final message = this.message.cast().toRealmDartString(); return LastError(error, message, user_code_error.toUserCodeError()); diff --git a/packages/realm_dart/lib/src/native/list_handle.dart b/packages/realm_dart/lib/src/native/list_handle.dart index abbc0e2f4..b6426e9f8 100644 --- a/packages/realm_dart/lib/src/native/list_handle.dart +++ b/packages/realm_dart/lib/src/native/list_handle.dart @@ -1,16 +1,29 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -part of 'realm_core.dart'; +import 'dart:ffi'; + +import 'package:ffi/ffi.dart'; + +import '../realm_dart.dart'; +import 'error_handling.dart'; +import 'object_handle.dart'; +import 'query_handle.dart'; +import 'realm_bindings.dart'; +import 'realm_core.dart'; // TODO: Remove this import +import 'realm_handle.dart'; +import 'realm_library.dart'; +import 'results_handle.dart'; +import 'rooted_handle.dart'; class ListHandle extends CollectionHandleBase { - ListHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 88); + ListHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 88); bool get isValid => realmLib.realm_list_is_valid(pointer); ResultsHandle asResults() { final ptr = invokeGetPointer(() => realmLib.realm_list_to_results(pointer)); - return ResultsHandle._(ptr, _root); + return ResultsHandle(ptr, root); } int get size { @@ -69,7 +82,7 @@ class ListHandle extends CollectionHandleBase { return using((Arena arena) { final resultPtr = arena>(); invokeGetBool(() => realmLib.realm_list_resolve_in(pointer, frozenRealm.pointer, resultPtr)); - return resultPtr == nullptr ? null : ListHandle._(resultPtr.value, _root); + return resultPtr == nullptr ? null : ListHandle(resultPtr.value, root); }); } @@ -89,12 +102,12 @@ class ListHandle extends CollectionHandleBase { ObjectHandle setEmbeddedAt(int index) { final ptr = invokeGetPointer(() => realmLib.realm_list_set_embedded(pointer, index)); - return ObjectHandle._(ptr, _root); + return ObjectHandle(ptr, root); } ObjectHandle insertEmbeddedAt(int index) { final ptr = invokeGetPointer(() => realmLib.realm_list_insert_embedded(pointer, index)); - return ObjectHandle._(ptr, _root); + return ObjectHandle(ptr, root); } ResultsHandle query(String query, List args) { @@ -104,7 +117,7 @@ class ListHandle extends CollectionHandleBase { for (var i = 0; i < length; ++i) { intoRealmQueryArg(args[i], argsPointer + i, arena); } - final queryHandle = QueryHandle._( + final queryHandle = QueryHandle( invokeGetPointer( () => realmLib.realm_query_parse_for_list( pointer, @@ -113,7 +126,7 @@ class ListHandle extends CollectionHandleBase { argsPointer, ), ), - _root); + root); return queryHandle.findAll(); }); } @@ -126,6 +139,6 @@ class ListHandle extends CollectionHandleBase { nullptr, Pointer.fromFunction(collectionChangeCallback), )); - return RealmNotificationTokenHandle._(ptr, _root); + return RealmNotificationTokenHandle(ptr, root); } } diff --git a/packages/realm_dart/lib/src/native/map_changes_handle.dart b/packages/realm_dart/lib/src/native/map_changes_handle.dart index d2557a5cc..79472e34d 100644 --- a/packages/realm_dart/lib/src/native/map_changes_handle.dart +++ b/packages/realm_dart/lib/src/native/map_changes_handle.dart @@ -1,10 +1,19 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -part of 'realm_core.dart'; + +import 'dart:ffi'; + +import 'package:ffi/ffi.dart'; + +import '../collections.dart'; +import 'handle_base.dart'; +import 'realm_bindings.dart'; +import 'realm_core.dart'; +import 'realm_library.dart'; class MapChangesHandle extends HandleBase { - MapChangesHandle._(Pointer pointer) : super(pointer, 256); + MapChangesHandle(Pointer pointer) : super(pointer, 256); MapChanges get changes { return using((arena) { diff --git a/packages/realm_dart/lib/src/native/map_handle.dart b/packages/realm_dart/lib/src/native/map_handle.dart index 2e836cbe4..5af9dcbcc 100644 --- a/packages/realm_dart/lib/src/native/map_handle.dart +++ b/packages/realm_dart/lib/src/native/map_handle.dart @@ -1,10 +1,24 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -part of 'realm_core.dart'; +import 'dart:ffi'; + +import 'package:ffi/ffi.dart'; + +import '../realm_dart.dart'; // TODO: remove this import +import 'error_handling.dart'; +import 'map_changes_handle.dart'; +import 'object_handle.dart'; +import 'query_handle.dart'; +import 'realm_bindings.dart'; +import 'realm_core.dart'; // TODO: remove this import +import 'realm_handle.dart'; +import 'realm_library.dart'; +import 'results_handle.dart'; +import 'rooted_handle.dart'; class MapHandle extends CollectionHandleBase { - MapHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 96); // TODO: check size + MapHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 96); // TODO: check size int get size { return using((Arena arena) { @@ -54,13 +68,13 @@ class MapHandle extends CollectionHandleBase { final outSize = arena(); final outKeys = arena>(); invokeGetBool(() => realmLib.realm_dictionary_get_keys(pointer, outSize, outKeys)); - return ResultsHandle._(outKeys.value, _root); + return ResultsHandle(outKeys.value, root); }); } ResultsHandle get values { final ptr = invokeGetPointer(() => realmLib.realm_dictionary_to_results(pointer)); - return ResultsHandle._(ptr, _root); + return ResultsHandle(ptr, root); } bool containsKey(String key) { @@ -88,7 +102,7 @@ class MapHandle extends CollectionHandleBase { return using((Arena arena) { final keyNative = toRealmValue(key, arena); final ptr = invokeGetPointer(() => realmLib.realm_dictionary_insert_embedded(pointer, keyNative.ref)); - return ObjectHandle._(ptr, _root); + return ObjectHandle(ptr, root); }); } @@ -128,7 +142,7 @@ class MapHandle extends CollectionHandleBase { intoRealmQueryArg(args[i], argsPointer + i, arena); } - final queryHandle = QueryHandle._( + final queryHandle = QueryHandle( invokeGetPointer( () => realmLib.realm_query_parse_for_results( values.pointer, @@ -137,7 +151,7 @@ class MapHandle extends CollectionHandleBase { argsPointer, ), ), - _root); + root); return queryHandle.findAll(); }); } @@ -146,7 +160,7 @@ class MapHandle extends CollectionHandleBase { return using((Arena arena) { final resultPtr = arena>(); invokeGetBool(() => realmLib.realm_dictionary_resolve_in(pointer, frozenRealm.pointer, resultPtr)); - return resultPtr == nullptr ? null : MapHandle._(resultPtr.value, _root); + return resultPtr == nullptr ? null : MapHandle(resultPtr.value, root); }); } @@ -158,7 +172,7 @@ class MapHandle extends CollectionHandleBase { nullptr, Pointer.fromFunction(_mapChangeCallback), )); - return RealmNotificationTokenHandle._(ptr, _root); + return RealmNotificationTokenHandle(ptr, root); } } @@ -177,7 +191,7 @@ void _mapChangeCallback(Pointer userdata, Pointer pointer, RealmHandle root) : super._(pointer.cast(), root); + MutableSubscriptionSetHandle(Pointer pointer, RealmHandle root) : super(pointer.cast(), root); Pointer get _mutablePointer => super.pointer.cast(); - SubscriptionSetHandle commit() => SubscriptionSetHandle._(invokeGetPointer(() => realmLib.realm_sync_subscription_set_commit(_mutablePointer)), _root); + SubscriptionSetHandle commit() => SubscriptionSetHandle(invokeGetPointer(() => realmLib.realm_sync_subscription_set_commit(_mutablePointer)), root); SubscriptionHandle insertOrAssignSubscription(ResultsHandle results, String? name, bool update) { if (!update) { diff --git a/packages/realm_dart/lib/src/native/object_handle.dart b/packages/realm_dart/lib/src/native/object_handle.dart index c3284fafa..b18072fa0 100644 --- a/packages/realm_dart/lib/src/native/object_handle.dart +++ b/packages/realm_dart/lib/src/native/object_handle.dart @@ -1,14 +1,29 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -part of 'realm_core.dart'; + +import 'dart:ffi'; + +import 'package:ffi/ffi.dart'; + +import '../realm_dart.dart'; // TODO: Remove this import +import 'error_handling.dart'; +import 'list_handle.dart'; +import 'map_handle.dart'; +import 'realm_bindings.dart'; +import 'realm_core.dart'; // TODO: Remove this import +import 'realm_handle.dart'; +import 'realm_library.dart'; +import 'results_handle.dart'; +import 'rooted_handle.dart'; +import 'set_handle.dart'; class ObjectHandle extends RootedHandleBase { - ObjectHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 112); + ObjectHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 112); ObjectHandle createEmbedded(int propertyKey) { final objectPtr = invokeGetPointer(() => realmLib.realm_set_embedded(pointer, propertyKey)); - return ObjectHandle._(objectPtr, _root); + return ObjectHandle(objectPtr, root); } (ObjectHandle, int) get parent { @@ -17,7 +32,7 @@ class ObjectHandle extends RootedHandleBase { final classKeyPtr = arena(); invokeGetBool(() => realmLib.realm_object_get_parent(pointer, parentPtr, classKeyPtr)); - final handle = ObjectHandle._(parentPtr.value, _root); + final handle = ObjectHandle(parentPtr.value, root); return (handle, classKeyPtr.value); }); @@ -58,22 +73,22 @@ class ObjectHandle extends RootedHandleBase { ListHandle getList(int propertyKey) { final ptr = invokeGetPointer(() => realmLib.realm_get_list(pointer, propertyKey)); - return ListHandle._(ptr, _root); + return ListHandle(ptr, root); } SetHandle getSet(int propertyKey) { final ptr = invokeGetPointer(() => realmLib.realm_get_set(pointer, propertyKey)); - return SetHandle._(ptr, _root); + return SetHandle(ptr, root); } MapHandle getMap(int propertyKey) { final ptr = invokeGetPointer(() => realmLib.realm_get_dictionary(pointer, propertyKey)); - return MapHandle._(ptr, _root); + return MapHandle(ptr, root); } ResultsHandle getBacklinks(int sourceTableKey, int propertyKey) { final ptr = invokeGetPointer(() => realmLib.realm_get_backlinks(pointer, sourceTableKey, propertyKey)); - return ResultsHandle._(ptr, _root); + return ResultsHandle(ptr, root); } void setCollection(Realm realm, int propertyKey, RealmValue value) { @@ -97,7 +112,7 @@ class ObjectHandle extends RootedHandleBase { return using((Arena arena) { final resultPtr = arena>(); invokeGetBool(() => realmLib.realm_object_resolve_in(pointer, frozenRealm.pointer, resultPtr)); - return resultPtr == nullptr ? null : ObjectHandle._(resultPtr.value, frozenRealm); + return resultPtr == nullptr ? null : ObjectHandle(resultPtr.value, frozenRealm); }); } @@ -112,7 +127,7 @@ class ObjectHandle extends RootedHandleBase { Pointer.fromFunction(_objectChangeCallback), )); - return RealmNotificationTokenHandle._(ptr, _root); + return RealmNotificationTokenHandle(ptr, root); }); } @@ -130,7 +145,7 @@ class ObjectHandle extends RootedHandleBase { } // TODO(kn): // call to classKey getter involves a native call, which is not ideal - return invokeGetPointer(() => realmLib.realm_create_key_path_array(_root.pointer, classKey, length, keypathsNative)); + return invokeGetPointer(() => realmLib.realm_create_key_path_array(root.pointer, classKey, length, keypathsNative)); }); } } @@ -150,7 +165,7 @@ void _objectChangeCallback(Pointer userdata, Pointer return; } - final changesHandle = RealmObjectChangesHandle._(clonedData.cast()); + final changesHandle = RealmObjectChangesHandle(clonedData.cast()); controller.onChanges(changesHandle); } catch (e) { controller.onError(RealmError("Error handling change notifications. Error: $e")); diff --git a/packages/realm_dart/lib/src/native/query_handle.dart b/packages/realm_dart/lib/src/native/query_handle.dart index e2e2dea5a..29016844a 100644 --- a/packages/realm_dart/lib/src/native/query_handle.dart +++ b/packages/realm_dart/lib/src/native/query_handle.dart @@ -1,15 +1,22 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -part of 'realm_core.dart'; +import 'dart:ffi'; + +import 'error_handling.dart'; +import 'realm_bindings.dart'; +import 'realm_handle.dart'; +import 'realm_library.dart'; +import 'results_handle.dart'; +import 'rooted_handle.dart'; class QueryHandle extends RootedHandleBase { - QueryHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 256); + QueryHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 256); ResultsHandle findAll() { try { final resultsPointer = invokeGetPointer(() => realmLib.realm_query_find_all(pointer)); - return ResultsHandle._(resultsPointer, _root); + return ResultsHandle(resultsPointer, root); } finally { release(); } diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index c2bf3db09..18448d5d8 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -5,7 +5,6 @@ import 'dart:async'; import 'dart:convert'; import 'dart:ffi'; import 'dart:io'; -import 'dart:isolate'; import 'dart:typed_data'; import 'package:cancellation_token/cancellation_token.dart'; @@ -14,48 +13,29 @@ import 'package:crypto/crypto.dart'; import 'package:ffi/ffi.dart' hide StringUtf8Pointer, StringUtf16Pointer; import 'package:path/path.dart' as path; import 'package:pubspec_parse/pubspec_parse.dart'; -import 'package:realm_common/realm_common.dart' as common show Decimal128; import 'package:realm_common/realm_common.dart' hide Decimal128; import '../app.dart'; -import '../collections.dart'; import '../configuration.dart'; -import '../credentials.dart'; import '../init.dart'; -import '../logging.dart'; -import '../migration.dart'; import '../realm_class.dart'; import '../realm_object.dart'; import '../scheduler.dart'; -import '../session.dart'; import '../user.dart'; +import 'app_handle.dart'; +import 'collection_changes_handle.dart'; +import 'config_handle.dart'; +import 'decimal128.dart'; +import 'error_handling.dart'; import 'handle_base.dart'; +import 'list_handle.dart'; +import 'map_handle.dart'; import 'realm_bindings.dart'; +import 'realm_handle.dart'; import 'realm_library.dart'; - -// TODO: Use regular imports -part 'app_handle.dart'; -part 'collection_changes_handle.dart'; -part 'config_handle.dart'; -part 'convert.dart'; -part 'credentials_handle.dart'; -part 'decimal128.dart'; -part 'error_handling.dart'; -part 'list_handle.dart'; -part 'map_changes_handle.dart'; -part 'map_handle.dart'; -part 'mutable_subscription_set_handle.dart'; -part 'object_handle.dart'; -part 'query_handle.dart'; -part 'realm_handle.dart'; -part 'results_handle.dart'; -part 'rooted_handle.dart'; -part 'schema_handle.dart'; -part 'session_handle.dart'; -part 'set_handle.dart'; -part 'subscription_handle.dart'; -part 'subscription_set_handle.dart'; -part 'user_handle.dart'; +import 'rooted_handle.dart'; +import 'session_handle.dart'; +import 'user_handle.dart'; final _pluginLib = () { if (!isFlutterPlatform) { @@ -205,7 +185,7 @@ void appUserCompletionCallback(Pointer userdata, Pointer user, return; } - completer.complete(UserHandle._(user.cast())); + completer.complete(UserHandle(user.cast())); } void voidCompletionCallback(Pointer userdata, Pointer error) { @@ -276,7 +256,7 @@ void createCollection(Realm realm, RealmValue value, Pointer Functio switch (value.collectionType) { case RealmCollectionType.list: final listPointer = invokeGetPointer(createList); - final listHandle = ListHandle._(listPointer, realm.handle); + final listHandle = ListHandle(listPointer, realm.handle); collectionHandle = listHandle; final list = realm.createList(listHandle, null); @@ -289,7 +269,7 @@ void createCollection(Realm realm, RealmValue value, Pointer Functio } case RealmCollectionType.map: final mapPointer = invokeGetPointer(createMap); - final mapHandle = MapHandle._(mapPointer, realm.handle); + final mapHandle = MapHandle(mapPointer, realm.handle); collectionHandle = mapHandle; final map = realm.createMap(mapHandle, null); @@ -323,7 +303,7 @@ void collectionChangeCallback(Pointer userdata, Pointer userdata, Pointer response, Poi // All access to Realm Core functionality goes through this class class _RealmCore { - // From realm.h. Currently not exported from the shared library - // ignore: unused_field, constant_identifier_names - static const int RLM_INVALID_CLASS_KEY = 0x7FFFFFFF; - // ignore: unused_field, constant_identifier_names - static const int RLM_INVALID_PROPERTY_KEY = -1; - // ignore: unused_field, constant_identifier_names - static const int RLM_INVALID_OBJECT_KEY = -1; - // ignore: unused_field static late final _RealmCore _instance; @@ -384,9 +356,9 @@ class _RealmCore { } RealmAsyncOpenTaskHandle createRealmAsyncOpenTask(FlexibleSyncConfiguration config) { - final configHandle = ConfigHandle(config); + final configHandle = ConfigHandle.from(config); final asyncOpenTaskPtr = invokeGetPointer(() => realmLib.realm_open_synchronized(configHandle.pointer), "Error opening realm at path ${config.path}"); - return RealmAsyncOpenTaskHandle._(asyncOpenTaskPtr); + return RealmAsyncOpenTaskHandle(asyncOpenTaskPtr); } Future openRealmAsync(RealmAsyncOpenTaskHandle handle, CancellationToken? cancellationToken) { @@ -419,7 +391,7 @@ class _RealmCore { } final realmPtr = invokeGetPointer(() => realmLib.realm_from_thread_safe_reference(realmSafePtr, scheduler.handle.pointer)); - completer.complete(RealmHandle._(realmPtr)); + completer.complete(RealmHandle(realmPtr)); }); } @@ -429,7 +401,7 @@ class _RealmCore { RealmAsyncOpenTaskProgressNotificationTokenHandle realmAsyncOpenRegisterAsyncOpenProgressNotifier( RealmAsyncOpenTaskHandle handle, RealmAsyncOpenProgressNotificationsController controller) { - final callback = Pointer.fromFunction(_syncProgressCallback); + final callback = Pointer.fromFunction(syncProgressCallback); final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); final tokenPtr = invokeGetPointer(() => realmLib.realm_async_open_task_register_download_progress_notifier( handle.pointer, @@ -437,7 +409,7 @@ class _RealmCore { userdata.cast(), realmLib.addresses.realm_dart_userdata_async_free, )); - return RealmAsyncOpenTaskProgressNotificationTokenHandle._(tokenPtr); + return RealmAsyncOpenTaskProgressNotificationTokenHandle(tokenPtr); } RealmSchema readSchema(Realm realm) { @@ -567,7 +539,7 @@ class _RealmCore { _RealmLinkHandle _getObjectAsLink(RealmObjectBase object) { final realmLink = realmLib.realm_object_as_link(object.handle.pointer); - return _RealmLinkHandle._(realmLink); + return _RealmLinkHandle(realmLink); } bool _equals(HandleBase first, HandleBase second) { @@ -616,7 +588,7 @@ class _RealmCore { return using((arena) { final outApp = arena>(); invokeGetBool(() => realmLib.realm_app_get_cached(id.toCharPtr(arena), baseUrl == null ? nullptr : baseUrl.toCharPtr(arena), outApp)); - return outApp.value == nullptr ? null : AppHandle._(outApp.value); + return outApp.value == nullptr ? null : AppHandle(outApp.value); }); } @@ -718,32 +690,32 @@ class _RealmCore { class _RealmLinkHandle { final int targetKey; final int classKey; - _RealmLinkHandle._(realm_link_t link) + _RealmLinkHandle(realm_link_t link) : targetKey = link.target, classKey = link.target_table; } -class RealmCallbackTokenHandle extends RootedHandleBase { - RealmCallbackTokenHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 32); +class CallbackTokenHandle extends RootedHandleBase { + CallbackTokenHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 32); } class RealmNotificationTokenHandle extends RootedHandleBase { - RealmNotificationTokenHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 32); + RealmNotificationTokenHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 32); } class RealmObjectChangesHandle extends HandleBase { - RealmObjectChangesHandle._(Pointer pointer) : super(pointer, 256); + RealmObjectChangesHandle(Pointer pointer) : super(pointer, 256); } class RealmAsyncOpenTaskHandle extends HandleBase { - RealmAsyncOpenTaskHandle._(Pointer pointer) : super(pointer, 32); + RealmAsyncOpenTaskHandle(Pointer pointer) : super(pointer, 32); } class RealmAsyncOpenTaskProgressNotificationTokenHandle extends HandleBase { - RealmAsyncOpenTaskProgressNotificationTokenHandle._(Pointer pointer) : super(pointer, 40); + RealmAsyncOpenTaskProgressNotificationTokenHandle(Pointer pointer) : super(pointer, 40); } -extension on List { +extension ListEx on List { Pointer toCharPtr(Allocator allocator) { return toUint8Ptr(allocator).cast(); } @@ -758,7 +730,7 @@ extension on List { } } -extension _StringEx on String { +extension StringEx on String { Pointer toCharPtr(Allocator allocator) { final units = utf8.encode(this); return units.toCharPtr(allocator).cast(); @@ -884,16 +856,26 @@ void intoRealmValue(Object? value, realm_value realmValue, Allocator allocator) } } -extension on Pointer { +extension PointerRealmValueEx on Pointer { Object? toDartValue(Realm realm, Pointer Function()? getList, Pointer Function()? getMap) { if (this == nullptr) { throw RealmException("Can not convert nullptr realm_value to Dart value"); } return ref.toDartValue(realm: realm, getList: getList, getMap: getMap); } + + List toStringList(int count) { + final result = List.filled(count, ''); + for (var i = 0; i < count; i++) { + final strValue = elementAt(i).ref.values.string; + result[i] = strValue.data.cast().toRealmDartString(length: strValue.size)!; + } + + return result; + } } -extension on realm_value_t { +extension RealmValueEx on realm_value_t { Object? toPrimitiveValue() => toDartValue(realm: null, getList: null, getMap: null); Object? toDartValue({required Realm? realm, required Pointer Function()? getList, required Pointer Function()? getMap}) { @@ -917,7 +899,7 @@ extension on realm_value_t { final objectKey = values.link.target; final classKey = values.link.target_table; if (realm.metadata.getByClassKeyIfExists(classKey) == null) return null; // temprorary workaround to avoid crash on assertion - return realm.handle._getObject(classKey, objectKey); + return realm.handle.getObject(classKey, objectKey); case realm_value_type.RLM_TYPE_BINARY: return Uint8List.fromList(values.binary.data.asTypedList(values.binary.size)); case realm_value_type.RLM_TYPE_TIMESTAMP: @@ -939,7 +921,7 @@ extension on realm_value_t { } final listPointer = invokeGetPointer(() => getList()); - final listHandle = ListHandle._(listPointer, realm.handle); + final listHandle = ListHandle(listPointer, realm.handle); return realm.createList(listHandle, null); case realm_value_type.RLM_TYPE_DICTIONARY: if (getMap == null || realm == null) { @@ -947,7 +929,7 @@ extension on realm_value_t { } final mapPointer = invokeGetPointer(() => getMap()); - final mapHandle = MapHandle._(mapPointer, realm.handle); + final mapHandle = MapHandle(mapPointer, realm.handle); return realm.createMap(mapHandle, null); default: throw RealmException("realm_value_type $type not supported"); @@ -955,7 +937,7 @@ extension on realm_value_t { } } -extension on Array { +extension ArrayUint8Ex on Array { List toList(int count) { final result = []; for (var i = 0; i < count; i++) { @@ -965,7 +947,7 @@ extension on Array { } } -extension on Pointer { +extension PointerSizeEx on Pointer { List toIntList(int count) { List result = List.filled(count, elementAt(0).value); for (var i = 1; i < count; i++) { @@ -975,19 +957,7 @@ extension on Pointer { } } -extension on Pointer { - List toStringList(int count) { - final result = List.filled(count, ''); - for (var i = 0; i < count; i++) { - final strValue = elementAt(i).ref.values.string; - result[i] = strValue.data.cast().toRealmDartString(length: strValue.size)!; - } - - return result; - } -} - -extension on Pointer { +extension PointerVoidEx on Pointer { T toObject() { assert(this != nullptr, "Pointer is null"); @@ -1008,7 +978,7 @@ extension on Pointer { } } -extension on Pointer { +extension PointerUtf8Ex on Pointer { String? toRealmDartString({bool treatEmptyAsNull = false, int? length, bool freeRealmMemory = false}) { if (this == nullptr) { return null; @@ -1029,7 +999,7 @@ extension on Pointer { } } -extension on realm_sync_error { +extension RealmSyncErrorEx on realm_sync_error { SyncErrorDetails toDart() { final message = status.message.cast().toRealmDartString()!; final userInfoMap = user_info_map.toDart(user_info_length); @@ -1049,7 +1019,7 @@ extension on realm_sync_error { } } -extension on Pointer { +extension PointerRealmSyncErrorUserInfoEx on Pointer { Map? toDart(int length) { if (this == nullptr) { return null; @@ -1065,7 +1035,7 @@ extension on Pointer { } } -extension on Pointer { +extension PointerRealmSyncErrorCompensatingWriteInfoEx on Pointer { List? toList(int length) { if (this == nullptr || length == 0) { return null; @@ -1082,7 +1052,7 @@ extension on Pointer { } } -extension on Pointer { +extension PointerRealmErrorEx on Pointer { SyncError toDart() { final message = ref.message.cast().toDartString(); final details = SyncErrorDetails(message, ref.error, ref.user_code_error.toUserCodeError()); @@ -1090,13 +1060,13 @@ extension on Pointer { } } -extension on Object { +extension ObjectEx on Object { Pointer toPersistentHandle() { return realmLib.realm_dart_object_to_persistent_handle(this); } } -extension on List { +extension ListUserStateEx on List { UserState fromIndex(int index) { if (!UserState.values.any((value) => value.index == index)) { throw RealmError("Unknown user state $index"); @@ -1106,7 +1076,7 @@ extension on List { } } -extension on realm_property_info { +extension RealmPropertyInfoEx on realm_property_info { SchemaProperty toSchemaProperty() { final linkTarget = link_target == nullptr ? null : link_target.cast().toDartString(); return SchemaProperty(name.cast().toDartString(), RealmPropertyType.values[type], @@ -1117,7 +1087,7 @@ extension on realm_property_info { } } -extension on Completer { +extension CompleterEx on Completer { void completeWithAppError(Pointer error) { final message = error.ref.message.cast().toRealmDartString()!; final linkToLogs = error.ref.link_to_server_logs.cast().toRealmDartString(); @@ -1125,17 +1095,17 @@ extension on Completer { } } -enum _CustomErrorCode { +enum CustomErrorCode { noError(0), unknownHttp(998), unknown(999), timeout(1000); final int code; - const _CustomErrorCode(this.code); + const CustomErrorCode(this.code); } -enum _HttpMethod { +enum HttpMethod { get, post, patch, @@ -1143,17 +1113,17 @@ enum _HttpMethod { delete, } -extension on realm_timestamp_t { +extension RealmTimestampEx on realm_timestamp_t { DateTime toDart() { return DateTime.fromMicrosecondsSinceEpoch(seconds * 1000000 + nanoseconds ~/ 1000, isUtc: true); } } -extension on realm_string_t { +extension RealmStringEx on realm_string_t { String? toDart() => data.cast().toRealmDartString(); } -extension on ObjectId { +extension ObjectIdEx on ObjectId { Pointer toNative(Allocator allocator) { final result = allocator(); for (var i = 0; i < 12; i++) { @@ -1163,7 +1133,7 @@ extension on ObjectId { } } -extension on realm_object_id { +extension RealmObjectIdEx on realm_object_id { ObjectId toDart() { final buffer = Uint8List(12); for (int i = 0; i < 12; ++i) { @@ -1173,7 +1143,7 @@ extension on realm_object_id { } } -extension on realm_app_user_apikey { +extension RealmAppUserApikeyEx on realm_app_user_apikey { ApiKey toDart() => UserInternal.createApiKey( id.toDart(), name.cast().toDartString(), @@ -1218,7 +1188,7 @@ class SyncErrorDetails { }); } -extension on RealmValueType { +extension RealmValueTypeEx on RealmValueType { String toQueryArgString() { return switch (this) { RealmValueType.nullValue => 'null', diff --git a/packages/realm_dart/lib/src/native/realm_handle.dart b/packages/realm_dart/lib/src/native/realm_handle.dart index 6a9c93de8..4e12b37b0 100644 --- a/packages/realm_dart/lib/src/native/realm_handle.dart +++ b/packages/realm_dart/lib/src/native/realm_handle.dart @@ -1,21 +1,42 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -part of 'realm_core.dart'; +import 'dart:async'; +import 'dart:ffi'; + +import 'package:cancellation_token/cancellation_token.dart'; +import 'package:ffi/ffi.dart'; + +import '../logging.dart'; +import '../realm_class.dart'; +import 'config_handle.dart'; +import 'convert.dart'; +import 'error_handling.dart'; +import 'handle_base.dart'; +import 'object_handle.dart'; +import 'query_handle.dart'; +import 'realm_bindings.dart'; +import 'realm_core.dart'; +import 'realm_library.dart'; +import 'results_handle.dart'; +import 'rooted_handle.dart'; +import 'schema_handle.dart'; +import 'session_handle.dart'; +import 'subscription_set_handle.dart'; class RealmHandle extends HandleBase { int _counter = 0; final Map> _children = {}; - RealmHandle._(Pointer pointer) : super(pointer, 24); + RealmHandle(Pointer pointer) : super(pointer, 24); - RealmHandle._unowned(super.pointer) : super.unowned(); + RealmHandle.unowned(super.pointer) : super.unowned(); factory RealmHandle.open(Configuration config) { - final configHandle = ConfigHandle(config); + final configHandle = ConfigHandle.from(config); final realmPtr = invokeGetPointer(() => realmLib.realm_open(configHandle.pointer), 'Error opening realm at path ${config.path}'); - return RealmHandle._(realmPtr); + return RealmHandle(realmPtr); } int addChild(RootedHandleBase child) { @@ -46,13 +67,13 @@ class RealmHandle extends HandleBase { return using((Arena arena) { final realmValue = toRealmValue(primaryKey, arena); final realmPtr = invokeGetPointer(() => realmLib.realm_object_create_with_primary_key(pointer, classKey, realmValue.ref)); - return ObjectHandle._(realmPtr, this); + return ObjectHandle(realmPtr, this); }); } ObjectHandle create(int classKey) { final realmPtr = invokeGetPointer(() => realmLib.realm_object_create(pointer, classKey)); - return ObjectHandle._(realmPtr, this); + return ObjectHandle(realmPtr, this); } ObjectHandle getOrCreateWithPrimaryKey(int classKey, Object? primaryKey) { @@ -65,7 +86,7 @@ class RealmHandle extends HandleBase { realmValue.ref, didCreate, )); - return ObjectHandle._(realmPtr, this); + return ObjectHandle(realmPtr, this); }); } @@ -78,7 +99,7 @@ class RealmHandle extends HandleBase { } void writeCopy(Configuration config) { - final configHandle = ConfigHandle(config); + final configHandle = ConfigHandle.from(config); invokeGetBool(() => realmLib.realm_convert_with_config(pointer, configHandle.pointer, false)); } @@ -89,7 +110,7 @@ class RealmHandle extends HandleBase { for (var i = 0; i < length; ++i) { intoRealmQueryArg(args[i], argsPointer + i, arena); } - final queryHandle = QueryHandle._( + final queryHandle = QueryHandle( invokeGetPointer( () => realmLib.realm_query_parse( pointer, @@ -104,10 +125,10 @@ class RealmHandle extends HandleBase { }); } - RealmHandle freeze() => RealmHandle._(invokeGetPointer(() => realmLib.realm_freeze(pointer))); + RealmHandle freeze() => RealmHandle(invokeGetPointer(() => realmLib.realm_freeze(pointer))); SessionHandle getSession() { - return SessionHandle._(invokeGetPointer(() => realmLib.realm_sync_session_get(pointer)), this); + return SessionHandle(invokeGetPointer(() => realmLib.realm_sync_session_get(pointer)), this); } bool get isFrozen { @@ -115,7 +136,7 @@ class RealmHandle extends HandleBase { } SubscriptionSetHandle get subscriptions { - return SubscriptionSetHandle._(invokeGetPointer(() => realmLib.realm_sync_get_active_subscription_set(pointer)), this); + return SubscriptionSetHandle(invokeGetPointer(() => realmLib.realm_sync_get_active_subscription_set(pointer)), this); } void disableAutoRefreshForTesting() { @@ -249,7 +270,7 @@ class RealmHandle extends HandleBase { ResultsHandle findAll(int classKey) { final ptr = invokeGetPointer(() => realmLib.realm_object_find_all(pointer, classKey)); - return ResultsHandle._(ptr, this); + return ResultsHandle(ptr, this); } ObjectHandle? find(int classKey, Object? primaryKey) { @@ -259,14 +280,14 @@ class RealmHandle extends HandleBase { if (ptr == nullptr) { return null; } - return ObjectHandle._(ptr, this); + return ObjectHandle(ptr, this); }); } ObjectHandle? findExisting(int classKey, ObjectHandle other) { final key = realmLib.realm_object_get_key(other.pointer); final ptr = invokeGetPointer(() => realmLib.realm_get_object(pointer, classKey, key)); - return ptr.convert((p) => ObjectHandle._(p, this)); + return ptr.convert((p) => ObjectHandle(p, this)); } void renameProperty(String objectType, String oldName, String newName, SchemaHandle schema) { @@ -284,12 +305,12 @@ class RealmHandle extends HandleBase { }); } - ObjectHandle _getObject(int classKey, int objectKey) { + ObjectHandle getObject(int classKey, int objectKey) { final ptr = invokeGetPointer(() => realmLib.realm_get_object(pointer, classKey, objectKey)); - return ObjectHandle._(ptr, this); + return ObjectHandle(ptr, this); } - RealmCallbackTokenHandle subscribeForSchemaNotifications(Realm realm) { + CallbackTokenHandle subscribeForSchemaNotifications(Realm realm) { final ptr = invokeGetPointer( () => realmLib.realm_add_schema_changed_callback( pointer, @@ -298,7 +319,7 @@ class RealmHandle extends HandleBase { realmLib.addresses.realm_dart_delete_persistent_handle, ), ); - return RealmCallbackTokenHandle._(ptr, this); + return CallbackTokenHandle(ptr, this); } } diff --git a/packages/realm_dart/lib/src/native/realm_library.dart b/packages/realm_dart/lib/src/native/realm_library.dart index f4c388176..beb96a051 100644 --- a/packages/realm_dart/lib/src/native/realm_library.dart +++ b/packages/realm_dart/lib/src/native/realm_library.dart @@ -1,4 +1,6 @@ -// This variable allows access to realm native library even before RealmCore is created. For Decimal128 for example +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + import 'package:ffi/ffi.dart'; import 'package:realm_common/realm_common.dart'; import 'package:realm_dart/src/init.dart'; diff --git a/packages/realm_dart/lib/src/native/results_handle.dart b/packages/realm_dart/lib/src/native/results_handle.dart index fe52c07f4..1d55a065a 100644 --- a/packages/realm_dart/lib/src/native/results_handle.dart +++ b/packages/realm_dart/lib/src/native/results_handle.dart @@ -1,19 +1,31 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -part of 'realm_core.dart'; +import 'dart:ffi'; + +import 'package:ffi/ffi.dart'; + +import '../realm_dart.dart'; +import 'error_handling.dart'; +import 'object_handle.dart'; +import 'query_handle.dart'; +import 'realm_bindings.dart'; +import 'realm_core.dart'; +import 'realm_handle.dart'; +import 'realm_library.dart'; +import 'rooted_handle.dart'; class ResultsHandle extends RootedHandleBase { - ResultsHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 872); + ResultsHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 872); ResultsHandle queryResults(String query, List args) { return using((arena) { final length = args.length; final argsPointer = arena(length); for (var i = 0; i < length; ++i) { - intoRealmQueryArg(args[i], argsPointer.elementAt(i), arena); + intoRealmQueryArg(args[i], argsPointer + i, arena); } - final queryHandle = QueryHandle._( + final queryHandle = QueryHandle( invokeGetPointer( () => realmLib.realm_query_parse_for_results( pointer, @@ -22,7 +34,7 @@ class ResultsHandle extends RootedHandleBase { argsPointer, ), ), - _root); + root); return queryHandle.findAll(); }); } @@ -48,7 +60,7 @@ class ResultsHandle extends RootedHandleBase { ObjectHandle getObjectAt(int index) { final objectPointer = invokeGetPointer(() => realmLib.realm_results_get_object(pointer, index)); - return ObjectHandle._(objectPointer, _root); + return ObjectHandle(objectPointer, root); } int get count { @@ -73,12 +85,12 @@ class ResultsHandle extends RootedHandleBase { ResultsHandle snapshot() { final resultsPointer = invokeGetPointer(() => realmLib.realm_results_snapshot(pointer)); - return ResultsHandle._(resultsPointer, _root); + return ResultsHandle(resultsPointer, root); } ResultsHandle resolveIn(RealmHandle realmHandle) { final ptr = invokeGetPointer(() => realmLib.realm_results_resolve_in(pointer, realmHandle.pointer)); - return ResultsHandle._(ptr, realmHandle); + return ResultsHandle(ptr, realmHandle); } Object? elementAt(Realm realm, int index) { @@ -103,6 +115,6 @@ class ResultsHandle extends RootedHandleBase { Pointer.fromFunction(collectionChangeCallback), ), ); - return RealmNotificationTokenHandle._(ptr, _root); + return RealmNotificationTokenHandle(ptr, root); } } diff --git a/packages/realm_dart/lib/src/native/rooted_handle.dart b/packages/realm_dart/lib/src/native/rooted_handle.dart index 11bb4fc7b..f1301dd42 100644 --- a/packages/realm_dart/lib/src/native/rooted_handle.dart +++ b/packages/realm_dart/lib/src/native/rooted_handle.dart @@ -1,7 +1,10 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -part of 'realm_core.dart'; +import 'dart:ffi'; + +import 'handle_base.dart'; +import 'realm_handle.dart'; class FinalizationToken { final WeakReference root; @@ -18,21 +21,21 @@ final rootedHandleFinalizer = Finalizer((token) { }); abstract class RootedHandleBase extends HandleBase { - final RealmHandle _root; + final RealmHandle root; int? _id; - bool get shouldRoot => _root.isUnowned; + bool get shouldRoot => root.isUnowned; - RootedHandleBase(this._root, Pointer pointer, int size) : super(pointer, size) { + RootedHandleBase(this.root, Pointer pointer, int size) : super(pointer, size) { if (shouldRoot) { - _id = _root.addChild(this); + _id = root.addChild(this); } } @override void releaseCore() { if (_id != null) { - _root.removeChild(_id!); + root.removeChild(_id!); } } } @@ -40,4 +43,3 @@ abstract class RootedHandleBase extends HandleBase { abstract class CollectionHandleBase extends RootedHandleBase { CollectionHandleBase(super.root, super.pointer, super.size); } - diff --git a/packages/realm_dart/lib/src/native/schema_handle.dart b/packages/realm_dart/lib/src/native/schema_handle.dart index c2afb6e16..39efd7228 100644 --- a/packages/realm_dart/lib/src/native/schema_handle.dart +++ b/packages/realm_dart/lib/src/native/schema_handle.dart @@ -1,14 +1,24 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -part of 'realm_core.dart'; +import 'dart:ffi'; + +import 'package:ffi/ffi.dart'; +import 'package:realm_common/realm_common.dart'; +import 'package:realm_dart/src/native/realm_core.dart'; + +import '../configuration.dart'; +import 'error_handling.dart'; +import 'handle_base.dart'; +import 'realm_bindings.dart'; +import 'realm_library.dart'; class SchemaHandle extends HandleBase { - SchemaHandle._(Pointer pointer) : super(pointer, 24); + SchemaHandle(Pointer pointer) : super(pointer, 24); SchemaHandle.unowned(super.pointer) : super.unowned(); - factory SchemaHandle(Iterable schema) { + factory SchemaHandle.from(Iterable schema) { return using((Arena arena) { final classCount = schema.length; @@ -17,7 +27,7 @@ class SchemaHandle extends HandleBase { for (var i = 0; i < classCount; i++) { final schemaObject = schema.elementAt(i); - final classInfo = schemaClasses.elementAt(i).ref; + final classInfo = (schemaClasses + i).ref; final propertiesCount = schemaObject.length; final computedCount = schemaObject.where((p) => p.isComputed).length; final persistedCount = propertiesCount - computedCount; @@ -26,14 +36,14 @@ class SchemaHandle extends HandleBase { classInfo.primary_key = "".toCharPtr(arena); classInfo.num_properties = persistedCount; classInfo.num_computed_properties = computedCount; - classInfo.key = _RealmCore.RLM_INVALID_CLASS_KEY; + classInfo.key = RLM_INVALID_CLASS_KEY; classInfo.flags = schemaObject.baseType.flags; final properties = arena(propertiesCount); for (var j = 0; j < propertiesCount; j++) { final schemaProperty = schemaObject[j]; - final propInfo = properties.elementAt(j).ref; + final propInfo = (properties + j).ref; propInfo.name = schemaProperty.mapTo.toCharPtr(arena); propInfo.public_name = (schemaProperty.mapTo != schemaProperty.name ? schemaProperty.name : '').toCharPtr(arena); propInfo.link_target = (schemaProperty.linkTarget ?? "").toCharPtr(arena); @@ -64,11 +74,19 @@ class SchemaHandle extends HandleBase { } schemaProperties[i] = properties; - schemaProperties.elementAt(i).value = properties; + (schemaProperties + i).value = properties; } final schemaPtr = invokeGetPointer(() => realmLib.realm_schema_new(schemaClasses, classCount, schemaProperties)); - return SchemaHandle._(schemaPtr); + return SchemaHandle(schemaPtr); }); } } + +// From realm.h. Currently not exported from the shared library +// ignore: unused_field, constant_identifier_names +const int RLM_INVALID_CLASS_KEY = 0x7FFFFFFF; +// ignore: unused_field, constant_identifier_names +const int RLM_INVALID_PROPERTY_KEY = -1; +// ignore: unused_field, constant_identifier_names +const int RLM_INVALID_OBJECT_KEY = -1; diff --git a/packages/realm_dart/lib/src/native/session_handle.dart b/packages/realm_dart/lib/src/native/session_handle.dart index 906f7268d..df91b229f 100644 --- a/packages/realm_dart/lib/src/native/session_handle.dart +++ b/packages/realm_dart/lib/src/native/session_handle.dart @@ -1,13 +1,28 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -part of 'realm_core.dart'; +import 'dart:ffi'; + +import 'package:cancellation_token/cancellation_token.dart'; +import 'package:ffi/ffi.dart'; + +import '../realm_dart.dart'; +import '../scheduler.dart'; +import '../session.dart'; // TODO: Remove this import +import 'error_handling.dart'; +import 'handle_base.dart'; +import 'realm_bindings.dart'; +import 'realm_core.dart'; // TODO: Remove this import +import 'realm_handle.dart'; +import 'realm_library.dart'; +import 'rooted_handle.dart'; +import 'user_handle.dart'; class SessionHandle extends RootedHandleBase { @override bool get shouldRoot => true; - SessionHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 24); + SessionHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 24); String get path { return realmLib.realm_sync_session_get_file_path(pointer).cast().toRealmDartString()!; @@ -19,7 +34,7 @@ class SessionHandle extends RootedHandleBase { } UserHandle get user { - return UserHandle._(realmLib.realm_sync_session_get_user(pointer)); + return UserHandle(realmLib.realm_sync_session_get_user(pointer)); } SessionState get state { @@ -110,7 +125,7 @@ class SessionHandle extends RootedHandleBase { realmLib.addresses.realm_dart_userdata_async_free, ), ); - return SyncSessionNotificationTokenHandle._(ptr); + return SyncSessionNotificationTokenHandle(ptr); } SyncSessionNotificationTokenHandle subscribeForProgressNotifications( @@ -119,7 +134,7 @@ class SessionHandle extends RootedHandleBase { SessionProgressNotificationsController controller, ) { final isStreaming = mode == ProgressMode.reportIndefinitely; - final callback = Pointer.fromFunction(_syncProgressCallback); + final callback = Pointer.fromFunction(syncProgressCallback); final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); final tokenPtr = invokeGetPointer(() => realmLib.realm_sync_session_register_progress_notifier( pointer, @@ -128,12 +143,12 @@ class SessionHandle extends RootedHandleBase { isStreaming, userdata.cast(), realmLib.addresses.realm_dart_userdata_async_free)); - return SyncSessionNotificationTokenHandle._(tokenPtr); + return SyncSessionNotificationTokenHandle(tokenPtr); } } class SyncSessionNotificationTokenHandle extends HandleBase { - SyncSessionNotificationTokenHandle._(Pointer pointer) : super(pointer, 32); + SyncSessionNotificationTokenHandle(Pointer pointer) : super(pointer, 32); } void _onConnectionStateChange(Object userdata, int oldState, int newState) { @@ -142,7 +157,7 @@ void _onConnectionStateChange(Object userdata, int oldState, int newState) { controller.onConnectionStateChange(ConnectionState.values[oldState], ConnectionState.values[newState]); } -void _syncProgressCallback(Object userdata, int transferred, int transferable, double estimate) { +void syncProgressCallback(Object userdata, int transferred, int transferable, double estimate) { final controller = userdata as ProgressNotificationsController; controller.onProgress(transferred, transferable); diff --git a/packages/realm_dart/lib/src/native/set_handle.dart b/packages/realm_dart/lib/src/native/set_handle.dart index c76600586..0c4571fd7 100644 --- a/packages/realm_dart/lib/src/native/set_handle.dart +++ b/packages/realm_dart/lib/src/native/set_handle.dart @@ -1,14 +1,26 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -part of 'realm_core.dart'; +import 'dart:ffi'; + +import 'package:ffi/ffi.dart'; + +import '../realm_dart.dart'; // TODO: remove this import +import 'error_handling.dart'; +import 'query_handle.dart'; +import 'realm_bindings.dart'; +import 'realm_core.dart'; // TODO: Remove this import +import 'realm_handle.dart'; +import 'realm_library.dart'; +import 'results_handle.dart'; +import 'rooted_handle.dart'; class SetHandle extends RootedHandleBase { - SetHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 96); + SetHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 96); ResultsHandle get asResults { final ptr = invokeGetPointer(() => realmLib.realm_set_to_results(pointer)); - return ResultsHandle._(ptr, _root); + return ResultsHandle(ptr, root); } ResultsHandle query(String query, List args) { @@ -18,7 +30,7 @@ class SetHandle extends RootedHandleBase { for (var i = 0; i < length; ++i) { intoRealmQueryArg(args[i], argsPointer + i, arena); } - final queryHandle = QueryHandle._( + final queryHandle = QueryHandle( invokeGetPointer( () => realmLib.realm_query_parse_for_set( pointer, @@ -27,7 +39,7 @@ class SetHandle extends RootedHandleBase { argsPointer, ), ), - _root); + root); return queryHandle.findAll(); }); } @@ -101,7 +113,7 @@ class SetHandle extends RootedHandleBase { return using((Arena arena) { final resultPtr = arena>(); invokeGetBool(() => realmLib.realm_set_resolve_in(pointer, frozenRealm.pointer, resultPtr)); - return resultPtr == nullptr ? null : SetHandle._(resultPtr.value, _root); + return resultPtr == nullptr ? null : SetHandle(resultPtr.value, root); }); } @@ -113,6 +125,6 @@ class SetHandle extends RootedHandleBase { nullptr, Pointer.fromFunction(collectionChangeCallback), )); - return RealmNotificationTokenHandle._(ptr, _root); + return RealmNotificationTokenHandle(ptr, root); } } diff --git a/packages/realm_dart/lib/src/native/subscription_handle.dart b/packages/realm_dart/lib/src/native/subscription_handle.dart index 9ee90a23c..4c2c67a2a 100644 --- a/packages/realm_dart/lib/src/native/subscription_handle.dart +++ b/packages/realm_dart/lib/src/native/subscription_handle.dart @@ -1,10 +1,16 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -part of 'realm_core.dart'; +import 'dart:ffi'; + +import '../realm_class.dart'; // TODO: Remove this import +import 'handle_base.dart'; +import 'realm_bindings.dart'; +import 'realm_core.dart'; // TODO: Remove this import +import 'realm_library.dart'; class SubscriptionHandle extends HandleBase { - SubscriptionHandle._(Pointer pointer) : super(pointer, 184); + SubscriptionHandle(Pointer pointer) : super(pointer, 184); ObjectId get id => realmLib.realm_sync_subscription_id(pointer).toDart(); diff --git a/packages/realm_dart/lib/src/native/subscription_set_handle.dart b/packages/realm_dart/lib/src/native/subscription_set_handle.dart index a184afec5..cdb675e29 100644 --- a/packages/realm_dart/lib/src/native/subscription_set_handle.dart +++ b/packages/realm_dart/lib/src/native/subscription_set_handle.dart @@ -1,13 +1,30 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -part of 'realm_core.dart'; +import 'dart:ffi'; + +import 'package:cancellation_token/cancellation_token.dart'; +import 'package:ffi/ffi.dart'; +import 'package:realm_dart/src/native/convert.dart'; + +import '../realm_dart.dart'; +import '../scheduler.dart'; +import '../subscription.dart'; +import 'error_handling.dart'; +import 'mutable_subscription_set_handle.dart'; +import 'realm_bindings.dart'; +import 'realm_core.dart'; // TODO: Remove this import +import 'realm_handle.dart'; +import 'realm_library.dart'; +import 'results_handle.dart'; +import 'rooted_handle.dart'; +import 'subscription_handle.dart'; class SubscriptionSetHandle extends RootedHandleBase { @override bool get shouldRoot => true; - SubscriptionSetHandle._(Pointer pointer, RealmHandle root) : super(root, pointer, 128); + SubscriptionSetHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 128); void refresh() => invokeGetBool(() => realmLib.realm_sync_subscription_set_refresh(pointer)); @@ -19,7 +36,7 @@ class SubscriptionSetHandle extends RootedHandleBase SubscriptionHandle._(invokeGetPointer(() => realmLib.realm_sync_subscription_at(pointer, index))); + SubscriptionHandle operator [](int index) => SubscriptionHandle(invokeGetPointer(() => realmLib.realm_sync_subscription_at(pointer, index))); SubscriptionHandle? findByName(String name) { return using((arena) { @@ -27,7 +44,7 @@ class SubscriptionSetHandle extends RootedHandleBase realmLib.realm_sync_subscription_set_version(pointer); @@ -44,7 +61,7 @@ class SubscriptionSetHandle extends RootedHandleBase SubscriptionSetState.values[realmLib.realm_sync_subscription_set_state(pointer)]; MutableSubscriptionSetHandle toMutable() => - MutableSubscriptionSetHandle._(invokeGetPointer(() => realmLib.realm_sync_make_subscription_set_mutable(pointer)), _root); + MutableSubscriptionSetHandle(invokeGetPointer(() => realmLib.realm_sync_make_subscription_set_mutable(pointer)), root); static void _stateChangeCallback(Object userdata, int state) { final completer = userdata as CancellableCompleter; diff --git a/packages/realm_dart/lib/src/native/user_handle.dart b/packages/realm_dart/lib/src/native/user_handle.dart index e4d699495..8b81d8610 100644 --- a/packages/realm_dart/lib/src/native/user_handle.dart +++ b/packages/realm_dart/lib/src/native/user_handle.dart @@ -1,13 +1,30 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -part of 'realm_core.dart'; +import 'dart:async'; +import 'dart:convert'; +import 'dart:ffi'; + +import 'package:ffi/ffi.dart'; + +import '../credentials.dart'; // TODO: Remove this import +import '../realm_dart.dart'; // TODO: Remove this import +import '../scheduler.dart'; +import '../user.dart'; // TODO: Remove this import +import 'app_handle.dart'; +import 'convert.dart'; +import 'credentials_handle.dart'; +import 'error_handling.dart'; +import 'handle_base.dart'; +import 'realm_bindings.dart'; +import 'realm_core.dart'; +import 'realm_library.dart'; // TODO: Remove this import class UserHandle extends HandleBase { - UserHandle._(Pointer pointer) : super(pointer, 24); + UserHandle(Pointer pointer) : super(pointer, 24); AppHandle get app { - return realmLib.realm_user_get_app(pointer).convert(AppHandle._) ?? + return realmLib.realm_user_get_app(pointer).convert(AppHandle.new) ?? (throw RealmException('User does not have an associated app. This is likely due to the user being logged out.')); } @@ -198,7 +215,7 @@ class UserHandle extends HandleBase { return using((Arena arena) { final completer = Completer(); final nativeId = objectId.toNative(arena); - + invokeGetBool( () => realmLib.realm_app_user_apikey_provider_client_enable_apikey( app.pointer, @@ -209,7 +226,7 @@ class UserHandle extends HandleBase { realmLib.addresses.realm_dart_userdata_async_free, ), ); - + return completer.future; }); } @@ -223,12 +240,12 @@ class UserHandle extends HandleBase { userdata.cast(), realmLib.addresses.realm_dart_userdata_async_free, ); - return UserNotificationTokenHandle._(notificationToken); + return UserNotificationTokenHandle(notificationToken); } } -class UserNotificationTokenHandle extends HandleBase { - UserNotificationTokenHandle._(Pointer pointer) : super(pointer, 32); +class UserNotificationTokenHandle extends HandleBase { + UserNotificationTokenHandle(Pointer pointer) : super(pointer, 32); } void _userChangeCallback(Object userdata, int data) { diff --git a/packages/realm_dart/lib/src/realm_class.dart b/packages/realm_dart/lib/src/realm_class.dart index 4e7f5c506..516689a59 100644 --- a/packages/realm_dart/lib/src/realm_class.dart +++ b/packages/realm_dart/lib/src/realm_class.dart @@ -14,7 +14,12 @@ import 'list.dart'; import 'logging.dart'; import 'map.dart'; import 'native/handle_base.dart'; +import 'native/list_handle.dart'; +import 'native/map_handle.dart'; +import 'native/object_handle.dart'; import 'native/realm_core.dart'; +import 'native/realm_handle.dart'; +import 'native/set_handle.dart'; import 'realm_object.dart'; import 'results.dart'; import 'scheduler.dart'; @@ -84,7 +89,8 @@ export 'list.dart' show RealmList, RealmListOfObject, RealmListChanges, ListExte export 'logging.dart' hide RealmLoggerInternal; export 'map.dart' show RealmMap, RealmMapChanges, RealmMapOfObject; export 'migration.dart' show Migration; -export 'native/realm_core.dart' show Decimal128, encryptionKeySize; +export 'native/realm_core.dart' show encryptionKeySize; +export 'native/decimal128.dart' show Decimal128; export 'realm_object.dart' show AsymmetricObject, @@ -111,7 +117,7 @@ class Realm implements Finalizable { late final RealmMetadata _metadata; late final RealmHandle _handle; final bool _isInMigration; - late final RealmCallbackTokenHandle? _schemaCallbackHandle; + late final CallbackTokenHandle? _schemaCallbackHandle; final List> _schemaChangeListeners = []; /// An object encompassing this `Realm` instance's dynamic API. diff --git a/packages/realm_dart/lib/src/realm_object.dart b/packages/realm_dart/lib/src/realm_object.dart index d868c6178..4f53c94d1 100644 --- a/packages/realm_dart/lib/src/realm_object.dart +++ b/packages/realm_dart/lib/src/realm_object.dart @@ -10,6 +10,7 @@ import 'package:realm_common/realm_common.dart'; import 'configuration.dart'; import 'list.dart'; import 'native/handle_base.dart'; +import 'native/object_handle.dart'; import 'native/realm_core.dart'; import 'native/realm_library.dart'; import 'realm_class.dart'; diff --git a/packages/realm_dart/lib/src/results.dart b/packages/realm_dart/lib/src/results.dart index 3cfdc2ced..f3cd2c128 100644 --- a/packages/realm_dart/lib/src/results.dart +++ b/packages/realm_dart/lib/src/results.dart @@ -7,8 +7,11 @@ import 'dart:ffi'; import 'package:cancellation_token/cancellation_token.dart'; import 'collections.dart'; +import 'native/collection_changes_handle.dart'; import 'native/handle_base.dart'; +import 'native/object_handle.dart'; import 'native/realm_core.dart'; +import 'native/results_handle.dart'; import 'realm_class.dart'; import 'realm_object.dart'; diff --git a/packages/realm_dart/lib/src/session.dart b/packages/realm_dart/lib/src/session.dart index d45ea7ecc..4b547e40d 100644 --- a/packages/realm_dart/lib/src/session.dart +++ b/packages/realm_dart/lib/src/session.dart @@ -3,11 +3,11 @@ import 'dart:async'; import 'dart:ffi'; -import '../realm.dart'; -import 'native/realm_core.dart'; -import 'user.dart'; +import '../realm.dart'; import '../src/native/realm_bindings.dart'; +import 'native/session_handle.dart'; +import 'user.dart'; /// An object encapsulating a synchronization session. Sessions represent the /// communication between the client (and a local Realm file on disk), and the diff --git a/packages/realm_dart/lib/src/set.dart b/packages/realm_dart/lib/src/set.dart index f776bcf4d..20cad6ee1 100644 --- a/packages/realm_dart/lib/src/set.dart +++ b/packages/realm_dart/lib/src/set.dart @@ -8,8 +8,11 @@ import 'dart:ffi'; import 'package:collection/collection.dart' as collection; +import 'native/collection_changes_handle.dart'; import 'native/handle_base.dart'; +import 'native/object_handle.dart'; import 'native/realm_core.dart'; +import 'native/set_handle.dart'; import 'realm_class.dart'; import 'realm_object.dart'; import 'collections.dart'; diff --git a/packages/realm_dart/lib/src/subscription.dart b/packages/realm_dart/lib/src/subscription.dart index 6ea976f0c..9b4a58eba 100644 --- a/packages/realm_dart/lib/src/subscription.dart +++ b/packages/realm_dart/lib/src/subscription.dart @@ -4,10 +4,12 @@ import 'dart:core'; import 'dart:ffi'; -import 'package:realm_dart/src/results.dart'; - -import 'native/realm_core.dart'; +import 'native/convert.dart'; +import 'native/mutable_subscription_set_handle.dart'; +import 'native/subscription_handle.dart'; +import 'native/subscription_set_handle.dart'; import 'realm_class.dart'; +import 'results.dart'; /// A class representing a single query subscription. The server will continuously /// evaluate the query that the app subscribed to and will send data diff --git a/packages/realm_dart/lib/src/user.dart b/packages/realm_dart/lib/src/user.dart index e186a7b13..48164d12c 100644 --- a/packages/realm_dart/lib/src/user.dart +++ b/packages/realm_dart/lib/src/user.dart @@ -8,6 +8,7 @@ import 'dart:ffi'; import 'app.dart'; import 'credentials.dart'; import 'native/realm_core.dart'; +import 'native/user_handle.dart'; import 'realm_class.dart'; /// Describes the changes to a [User] instance - for example when the access token is updated or the user state changes. diff --git a/packages/realm_dart/test/decimal128_test.dart b/packages/realm_dart/test/decimal128_test.dart index ef6d76111..85aec4ca7 100644 --- a/packages/realm_dart/test/decimal128_test.dart +++ b/packages/realm_dart/test/decimal128_test.dart @@ -4,6 +4,7 @@ import 'dart:math'; import 'package:meta/meta.dart'; +import 'package:realm_dart/src/native/decimal128.dart'; import 'package:test/expect.dart' hide throws; import 'package:realm_dart/src/native/realm_core.dart'; diff --git a/packages/realm_dart/test/dynamic_realm_test.dart b/packages/realm_dart/test/dynamic_realm_test.dart index e5c218412..8d2580c5b 100644 --- a/packages/realm_dart/test/dynamic_realm_test.dart +++ b/packages/realm_dart/test/dynamic_realm_test.dart @@ -4,9 +4,7 @@ // ignore_for_file: avoid_relative_lib_imports import 'package:collection/collection.dart'; -import 'dart:ffi'; import 'dart:typed_data'; -import 'package:test/test.dart' hide test, throws; import 'package:realm_dart/realm.dart'; import 'test.dart'; diff --git a/packages/realm_dart/test/embedded_test.dart b/packages/realm_dart/test/embedded_test.dart index 431f32874..9936d7d67 100644 --- a/packages/realm_dart/test/embedded_test.dart +++ b/packages/realm_dart/test/embedded_test.dart @@ -1,6 +1,7 @@ // Copyright 2022 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 +import 'package:realm_dart/src/native/decimal128.dart'; import 'package:test/test.dart' hide test, throws; import 'package:realm_dart/realm.dart'; From 5c627500a3ff506a6d8a161d26b56a9a360827be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Thu, 25 Apr 2024 22:09:19 +0200 Subject: [PATCH 49/68] Move XTokenHandles --- packages/realm_dart/lib/src/list.dart | 2 +- packages/realm_dart/lib/src/map.dart | 2 +- .../lib/src/native/list_handle.dart | 4 +- .../realm_dart/lib/src/native/map_handle.dart | 4 +- .../lib/src/native/object_handle.dart | 27 ++++- .../realm_dart/lib/src/native/realm_core.dart | 109 +++--------------- .../lib/src/native/realm_handle.dart | 4 + .../lib/src/native/results_handle.dart | 4 +- .../realm_dart/lib/src/native/set_handle.dart | 4 +- .../lib/src/native/user_handle.dart | 66 ++++++++++- packages/realm_dart/lib/src/realm_class.dart | 8 +- packages/realm_dart/lib/src/realm_object.dart | 10 +- packages/realm_dart/lib/src/results.dart | 2 +- packages/realm_dart/lib/src/set.dart | 2 +- 14 files changed, 124 insertions(+), 124 deletions(-) diff --git a/packages/realm_dart/lib/src/list.dart b/packages/realm_dart/lib/src/list.dart index f13e1fe5e..3634a841c 100644 --- a/packages/realm_dart/lib/src/list.dart +++ b/packages/realm_dart/lib/src/list.dart @@ -338,7 +338,7 @@ class ListNotificationsController extends NotificationsContro ListNotificationsController(this.list); @override - RealmNotificationTokenHandle subscribe() { + NotificationTokenHandle subscribe() { return list.handle.subscribeForNotifications(this); } diff --git a/packages/realm_dart/lib/src/map.dart b/packages/realm_dart/lib/src/map.dart index d9c242f01..a0ef02874 100644 --- a/packages/realm_dart/lib/src/map.dart +++ b/packages/realm_dart/lib/src/map.dart @@ -289,7 +289,7 @@ class MapNotificationsController extends NotificationsControl MapNotificationsController(this.map); @override - RealmNotificationTokenHandle subscribe() { + NotificationTokenHandle subscribe() { return map.handle.subscribeForNotifications(this); } diff --git a/packages/realm_dart/lib/src/native/list_handle.dart b/packages/realm_dart/lib/src/native/list_handle.dart index b6426e9f8..2d515ef57 100644 --- a/packages/realm_dart/lib/src/native/list_handle.dart +++ b/packages/realm_dart/lib/src/native/list_handle.dart @@ -131,7 +131,7 @@ class ListHandle extends CollectionHandleBase { }); } - RealmNotificationTokenHandle subscribeForNotifications(NotificationsController controller) { + NotificationTokenHandle subscribeForNotifications(NotificationsController controller) { final ptr = invokeGetPointer(() => realmLib.realm_list_add_notification_callback( pointer, controller.toPersistentHandle(), @@ -139,6 +139,6 @@ class ListHandle extends CollectionHandleBase { nullptr, Pointer.fromFunction(collectionChangeCallback), )); - return RealmNotificationTokenHandle(ptr, root); + return NotificationTokenHandle(ptr, root); } } diff --git a/packages/realm_dart/lib/src/native/map_handle.dart b/packages/realm_dart/lib/src/native/map_handle.dart index 5af9dcbcc..fabf1c1c3 100644 --- a/packages/realm_dart/lib/src/native/map_handle.dart +++ b/packages/realm_dart/lib/src/native/map_handle.dart @@ -164,7 +164,7 @@ class MapHandle extends CollectionHandleBase { }); } - RealmNotificationTokenHandle subscribeForNotifications(NotificationsController controller) { + NotificationTokenHandle subscribeForNotifications(NotificationsController controller) { final ptr = invokeGetPointer(() => realmLib.realm_dictionary_add_notification_callback( pointer, controller.toPersistentHandle(), @@ -172,7 +172,7 @@ class MapHandle extends CollectionHandleBase { nullptr, Pointer.fromFunction(_mapChangeCallback), )); - return RealmNotificationTokenHandle(ptr, root); + return NotificationTokenHandle(ptr, root); } } diff --git a/packages/realm_dart/lib/src/native/object_handle.dart b/packages/realm_dart/lib/src/native/object_handle.dart index b18072fa0..6f8a63f9c 100644 --- a/packages/realm_dart/lib/src/native/object_handle.dart +++ b/packages/realm_dart/lib/src/native/object_handle.dart @@ -1,13 +1,13 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 - import 'dart:ffi'; import 'package:ffi/ffi.dart'; import '../realm_dart.dart'; // TODO: Remove this import import 'error_handling.dart'; +import 'handle_base.dart'; import 'list_handle.dart'; import 'map_handle.dart'; import 'realm_bindings.dart'; @@ -116,7 +116,7 @@ class ObjectHandle extends RootedHandleBase { }); } - RealmNotificationTokenHandle subscribeForNotifications(NotificationsController controller, [List? keyPaths]) { + NotificationTokenHandle subscribeForNotifications(NotificationsController controller, [List? keyPaths]) { return using((Arena arena) { final kpNative = buildAndVerifyKeyPath(keyPaths); final ptr = invokeGetPointer(() => realmLib.realm_object_add_notification_callback( @@ -127,7 +127,7 @@ class ObjectHandle extends RootedHandleBase { Pointer.fromFunction(_objectChangeCallback), )); - return RealmNotificationTokenHandle(ptr, root); + return NotificationTokenHandle(ptr, root); }); } @@ -165,9 +165,28 @@ void _objectChangeCallback(Pointer userdata, Pointer return; } - final changesHandle = RealmObjectChangesHandle(clonedData.cast()); + final changesHandle = ObjectChangesHandle(clonedData.cast()); controller.onChanges(changesHandle); } catch (e) { controller.onError(RealmError("Error handling change notifications. Error: $e")); } } + +class ObjectChangesHandle extends HandleBase { + ObjectChangesHandle(Pointer pointer) : super(pointer, 256); + + bool get isDeleted { + return realmLib.realm_object_changes_is_deleted(pointer); + } + + List get properties { + return using((arena) { + final count = realmLib.realm_object_changes_get_num_modified_properties(pointer); + + final outModified = arena(count); + realmLib.realm_object_changes_get_modified_properties(pointer, outModified, count); + + return outModified.asTypedList(count).toList(); + }); + } +} diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 18448d5d8..4699144af 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -146,31 +146,6 @@ Pointer createAsyncUserCallbackUserdata(Completer completer) { return userdata.cast(); } -void appApiKeyCompletionCallback(Pointer userdata, Pointer apiKey, Pointer error) { - final Completer completer = userdata.toObject(); - if (error != nullptr) { - completer.completeWithAppError(error); - return; - } - completer.complete(apiKey.ref.toDart()); -} - -void appApiKeyArrayCompletionCallback(Pointer userdata, Pointer apiKey, int size, Pointer error) { - final Completer> completer = userdata.toObject(); - - if (error != nullptr) { - completer.completeWithAppError(error); - return; - } - - final result = []; - for (var i = 0; i < size; i++) { - result.add(apiKey[i].toDart()); - } - - completer.complete(result); -} - void appUserCompletionCallback(Pointer userdata, Pointer user, Pointer error) { final Completer completer = userdata.toObject(); @@ -215,41 +190,6 @@ Pointer createAsyncCallbackUserdata(Completer co return userdata.cast(); } -Pointer createAsyncApikeyCallbackUserdata(Completer completer) { - final callback = Pointer.fromFunction< - Void Function( - Pointer, - Pointer, - Pointer, - )>(appApiKeyCompletionCallback); - - final userdata = realmLib.realm_dart_userdata_async_new( - completer, - callback.cast(), - scheduler.handle.pointer, - ); - - return userdata.cast(); -} - -Pointer createAsyncApikeyListCallbackUserdata(Completer> completer) { - final callback = Pointer.fromFunction< - Void Function( - Pointer, - Pointer, - Size count, - Pointer, - )>(appApiKeyArrayCompletionCallback); - - final userdata = realmLib.realm_dart_userdata_async_new( - completer, - callback.cast(), - scheduler.handle.pointer, - ); - - return userdata.cast(); -} - void createCollection(Realm realm, RealmValue value, Pointer Function() createList, Pointer Function() createMap) { CollectionHandleBase? collectionHandle; try { @@ -355,13 +295,13 @@ class _RealmCore { realmLib.realm_scheduler_perform_work(queuePointer); } - RealmAsyncOpenTaskHandle createRealmAsyncOpenTask(FlexibleSyncConfiguration config) { + AsyncOpenTaskHandle createRealmAsyncOpenTask(FlexibleSyncConfiguration config) { final configHandle = ConfigHandle.from(config); final asyncOpenTaskPtr = invokeGetPointer(() => realmLib.realm_open_synchronized(configHandle.pointer), "Error opening realm at path ${config.path}"); - return RealmAsyncOpenTaskHandle(asyncOpenTaskPtr); + return AsyncOpenTaskHandle(asyncOpenTaskPtr); } - Future openRealmAsync(RealmAsyncOpenTaskHandle handle, CancellationToken? cancellationToken) { + Future openRealmAsync(AsyncOpenTaskHandle handle, CancellationToken? cancellationToken) { final completer = CancellableCompleter(cancellationToken); if (!completer.isCancelled) { final callback = @@ -395,12 +335,12 @@ class _RealmCore { }); } - void cancelOpenRealmAsync(RealmAsyncOpenTaskHandle handle) { + void cancelOpenRealmAsync(AsyncOpenTaskHandle handle) { realmLib.realm_async_open_task_cancel(handle.pointer); } - RealmAsyncOpenTaskProgressNotificationTokenHandle realmAsyncOpenRegisterAsyncOpenProgressNotifier( - RealmAsyncOpenTaskHandle handle, RealmAsyncOpenProgressNotificationsController controller) { + AsyncOpenTaskProgressNotificationTokenHandle realmAsyncOpenRegisterAsyncOpenProgressNotifier( + AsyncOpenTaskHandle handle, RealmAsyncOpenProgressNotificationsController controller) { final callback = Pointer.fromFunction(syncProgressCallback); final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); final tokenPtr = invokeGetPointer(() => realmLib.realm_async_open_task_register_download_progress_notifier( @@ -409,7 +349,7 @@ class _RealmCore { userdata.cast(), realmLib.addresses.realm_dart_userdata_async_free, )); - return RealmAsyncOpenTaskProgressNotificationTokenHandle(tokenPtr); + return AsyncOpenTaskProgressNotificationTokenHandle(tokenPtr); } RealmSchema readSchema(Realm realm) { @@ -559,21 +499,6 @@ class _RealmCore { return hashCode; } - bool getObjectChangesIsDeleted(RealmObjectChangesHandle handle) { - return realmLib.realm_object_changes_is_deleted(handle.pointer); - } - - List getObjectChangesProperties(RealmObjectChangesHandle handle) { - return using((arena) { - final count = realmLib.realm_object_changes_get_num_modified_properties(handle.pointer); - - final outModified = arena(count); - realmLib.realm_object_changes_get_modified_properties(handle.pointer, outModified, count); - - return outModified.asTypedList(count).toList(); - }); - } - void logMessage(LogCategory category, LogLevel logLevel, String message) { return using((arena) { realmLib.realm_dart_log(logLevel.index, category.toString().toCharPtr(arena), message.toCharPtr(arena)); @@ -695,24 +620,16 @@ class _RealmLinkHandle { classKey = link.target_table; } -class CallbackTokenHandle extends RootedHandleBase { - CallbackTokenHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 32); -} - -class RealmNotificationTokenHandle extends RootedHandleBase { - RealmNotificationTokenHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 32); -} - -class RealmObjectChangesHandle extends HandleBase { - RealmObjectChangesHandle(Pointer pointer) : super(pointer, 256); +class NotificationTokenHandle extends RootedHandleBase { + NotificationTokenHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 32); } -class RealmAsyncOpenTaskHandle extends HandleBase { - RealmAsyncOpenTaskHandle(Pointer pointer) : super(pointer, 32); +class AsyncOpenTaskHandle extends HandleBase { + AsyncOpenTaskHandle(Pointer pointer) : super(pointer, 32); } -class RealmAsyncOpenTaskProgressNotificationTokenHandle extends HandleBase { - RealmAsyncOpenTaskProgressNotificationTokenHandle(Pointer pointer) : super(pointer, 40); +class AsyncOpenTaskProgressNotificationTokenHandle extends HandleBase { + AsyncOpenTaskProgressNotificationTokenHandle(Pointer pointer) : super(pointer, 40); } extension ListEx on List { diff --git a/packages/realm_dart/lib/src/native/realm_handle.dart b/packages/realm_dart/lib/src/native/realm_handle.dart index 4e12b37b0..a55b28810 100644 --- a/packages/realm_dart/lib/src/native/realm_handle.dart +++ b/packages/realm_dart/lib/src/native/realm_handle.dart @@ -323,6 +323,10 @@ class RealmHandle extends HandleBase { } } +class CallbackTokenHandle extends RootedHandleBase { + CallbackTokenHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 32); +} + void _schemaChangeCallback(Pointer userdata, Pointer data) { final Realm realm = userdata.toObject(); try { diff --git a/packages/realm_dart/lib/src/native/results_handle.dart b/packages/realm_dart/lib/src/native/results_handle.dart index 1d55a065a..d43e80c29 100644 --- a/packages/realm_dart/lib/src/native/results_handle.dart +++ b/packages/realm_dart/lib/src/native/results_handle.dart @@ -105,7 +105,7 @@ class ResultsHandle extends RootedHandleBase { }); } - RealmNotificationTokenHandle subscribeForNotifications(NotificationsController controller) { + NotificationTokenHandle subscribeForNotifications(NotificationsController controller) { final ptr = invokeGetPointer( () => realmLib.realm_results_add_notification_callback( pointer, @@ -115,6 +115,6 @@ class ResultsHandle extends RootedHandleBase { Pointer.fromFunction(collectionChangeCallback), ), ); - return RealmNotificationTokenHandle(ptr, root); + return NotificationTokenHandle(ptr, root); } } diff --git a/packages/realm_dart/lib/src/native/set_handle.dart b/packages/realm_dart/lib/src/native/set_handle.dart index 0c4571fd7..f2cdcf724 100644 --- a/packages/realm_dart/lib/src/native/set_handle.dart +++ b/packages/realm_dart/lib/src/native/set_handle.dart @@ -117,7 +117,7 @@ class SetHandle extends RootedHandleBase { }); } - RealmNotificationTokenHandle subscribeForNotifications(NotificationsController controller) { + NotificationTokenHandle subscribeForNotifications(NotificationsController controller) { final ptr = invokeGetPointer(() => realmLib.realm_set_add_notification_callback( pointer, controller.toPersistentHandle(), @@ -125,6 +125,6 @@ class SetHandle extends RootedHandleBase { nullptr, Pointer.fromFunction(collectionChangeCallback), )); - return RealmNotificationTokenHandle(ptr, root); + return NotificationTokenHandle(ptr, root); } } diff --git a/packages/realm_dart/lib/src/native/user_handle.dart b/packages/realm_dart/lib/src/native/user_handle.dart index 8b81d8610..42438501b 100644 --- a/packages/realm_dart/lib/src/native/user_handle.dart +++ b/packages/realm_dart/lib/src/native/user_handle.dart @@ -133,7 +133,7 @@ class UserHandle extends HandleBase { pointer, namePtr, realmLib.addresses.realm_dart_apikey_callback, - createAsyncApikeyCallbackUserdata(completer), + _createAsyncApikeyCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ), ); @@ -151,7 +151,7 @@ class UserHandle extends HandleBase { pointer, nativeId.ref, realmLib.addresses.realm_dart_apikey_callback, - createAsyncApikeyCallbackUserdata(completer), + _createAsyncApikeyCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, )); @@ -166,7 +166,7 @@ class UserHandle extends HandleBase { app.pointer, pointer, realmLib.addresses.realm_dart_apikey_list_callback, - createAsyncApikeyListCallbackUserdata(completer), + _createAsyncApikeyListCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, )); @@ -253,3 +253,63 @@ void _userChangeCallback(Object userdata, int data) { controller.onUserChanged(); } + +Pointer _createAsyncApikeyCallbackUserdata(Completer completer) { + final callback = Pointer.fromFunction< + Void Function( + Pointer, + Pointer, + Pointer, + )>(_appApiKeyCompletionCallback); + + final userdata = realmLib.realm_dart_userdata_async_new( + completer, + callback.cast(), + scheduler.handle.pointer, + ); + + return userdata.cast(); +} + +void _appApiKeyCompletionCallback(Pointer userdata, Pointer apiKey, Pointer error) { + final Completer completer = userdata.toObject(); + if (error != nullptr) { + completer.completeWithAppError(error); + return; + } + completer.complete(apiKey.ref.toDart()); +} + +Pointer _createAsyncApikeyListCallbackUserdata(Completer> completer) { + final callback = Pointer.fromFunction< + Void Function( + Pointer, + Pointer, + Size count, + Pointer, + )>(_appApiKeyArrayCompletionCallback); + + final userdata = realmLib.realm_dart_userdata_async_new( + completer, + callback.cast(), + scheduler.handle.pointer, + ); + + return userdata.cast(); +} + +void _appApiKeyArrayCompletionCallback(Pointer userdata, Pointer apiKey, int size, Pointer error) { + final Completer> completer = userdata.toObject(); + + if (error != nullptr) { + completer.completeWithAppError(error); + return; + } + + final result = []; + for (var i = 0; i < size; i++) { + result.add(apiKey[i].toDart()); + } + + completer.complete(result); +} diff --git a/packages/realm_dart/lib/src/realm_class.dart b/packages/realm_dart/lib/src/realm_class.dart index 516689a59..401146751 100644 --- a/packages/realm_dart/lib/src/realm_class.dart +++ b/packages/realm_dart/lib/src/realm_class.dart @@ -862,9 +862,9 @@ extension RealmInternal on Realm { /// @nodoc abstract class NotificationsController implements Finalizable { - RealmNotificationTokenHandle? handle; + NotificationTokenHandle? handle; - RealmNotificationTokenHandle subscribe(); + NotificationTokenHandle subscribe(); void onChanges(HandleBase changesHandle); void onError(RealmError error); @@ -1027,8 +1027,8 @@ typedef ProgressCallback = void Function(SyncProgress syncProgress); /// @nodoc class RealmAsyncOpenProgressNotificationsController implements ProgressNotificationsController { - final RealmAsyncOpenTaskHandle _handle; - RealmAsyncOpenTaskProgressNotificationTokenHandle? _tokenHandle; + final AsyncOpenTaskHandle _handle; + AsyncOpenTaskProgressNotificationTokenHandle? _tokenHandle; late final StreamController _streamController; RealmAsyncOpenProgressNotificationsController._(this._handle); diff --git a/packages/realm_dart/lib/src/realm_object.dart b/packages/realm_dart/lib/src/realm_object.dart index 4f53c94d1..ae4f25272 100644 --- a/packages/realm_dart/lib/src/realm_object.dart +++ b/packages/realm_dart/lib/src/realm_object.dart @@ -728,17 +728,17 @@ class UserCallbackException extends RealmException { /// Describes the changes in on a single RealmObject since the last time the notification callback was invoked. class RealmObjectChanges implements Finalizable { // ignore: unused_field - final RealmObjectChangesHandle _handle; + final ObjectChangesHandle _handle; /// The realm object being monitored for changes. final T object; /// `True` if the object was deleted. - bool get isDeleted => realmCore.getObjectChangesIsDeleted(_handle); + bool get isDeleted => _handle.isDeleted; /// The property names that have changed. List get properties { - final propertyKeys = realmCore.getObjectChangesProperties(_handle); + final propertyKeys = _handle.properties; return object.realm .getPropertyNames(object, propertyKeys) .map((e) => object.objectSchema.firstWhere((element) => element.mapTo == e || element.name == e).name) @@ -775,7 +775,7 @@ class RealmObjectNotificationsController extends Noti } @override - RealmNotificationTokenHandle subscribe() { + NotificationTokenHandle subscribe() { return realmObject.handle.subscribeForNotifications(this, keyPaths); } @@ -786,7 +786,7 @@ class RealmObjectNotificationsController extends Noti @override void onChanges(HandleBase changesHandle) { - if (changesHandle is! RealmObjectChangesHandle) { + if (changesHandle is! ObjectChangesHandle) { throw RealmError("Invalid changes handle. RealmObjectChangesHandle expected"); } diff --git a/packages/realm_dart/lib/src/results.dart b/packages/realm_dart/lib/src/results.dart index f3cd2c128..e399b2b80 100644 --- a/packages/realm_dart/lib/src/results.dart +++ b/packages/realm_dart/lib/src/results.dart @@ -316,7 +316,7 @@ class ResultsNotificationsController extends NotificationsCon ResultsNotificationsController(this.results); @override - RealmNotificationTokenHandle subscribe() { + NotificationTokenHandle subscribe() { return results.handle.subscribeForNotifications(this); } diff --git a/packages/realm_dart/lib/src/set.dart b/packages/realm_dart/lib/src/set.dart index 20cad6ee1..a0bd4f573 100644 --- a/packages/realm_dart/lib/src/set.dart +++ b/packages/realm_dart/lib/src/set.dart @@ -341,7 +341,7 @@ class RealmSetNotificationsController extends NotificationsCo RealmSetNotificationsController(this.set); @override - RealmNotificationTokenHandle subscribe() { + NotificationTokenHandle subscribe() { return set.handle.subscribeForNotifications(this); } From 0e3acef7bc8dd353899353a5881692590aa1ad33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Thu, 25 Apr 2024 22:21:32 +0200 Subject: [PATCH 50/68] toNative extension method replaces toRealmValue function --- packages/realm_dart/lib/src/collections.dart | 1 - .../realm_dart/lib/src/configuration.dart | 2 +- .../realm_dart/lib/src/native/app_handle.dart | 1 - .../lib/src/native/list_handle.dart | 4 +-- .../realm_dart/lib/src/native/map_handle.dart | 16 ++++----- .../lib/src/native/object_handle.dart | 2 +- .../realm_dart/lib/src/native/realm_core.dart | 34 ++++++++++--------- .../lib/src/native/realm_handle.dart | 6 ++-- .../lib/src/native/results_handle.dart | 2 +- .../realm_dart/lib/src/native/set_handle.dart | 6 ++-- .../src/native/subscription_set_handle.dart | 1 - 11 files changed, 37 insertions(+), 38 deletions(-) diff --git a/packages/realm_dart/lib/src/collections.dart b/packages/realm_dart/lib/src/collections.dart index 47e74ff71..71b25dfd0 100644 --- a/packages/realm_dart/lib/src/collections.dart +++ b/packages/realm_dart/lib/src/collections.dart @@ -3,7 +3,6 @@ import 'dart:ffi'; import 'native/collection_changes_handle.dart'; -import 'native/realm_core.dart'; /// Contains index information about objects that moved within the same collection. class Move { diff --git a/packages/realm_dart/lib/src/configuration.dart b/packages/realm_dart/lib/src/configuration.dart index 5d8c7abcd..c05d8bb20 100644 --- a/packages/realm_dart/lib/src/configuration.dart +++ b/packages/realm_dart/lib/src/configuration.dart @@ -655,7 +655,7 @@ class ClientResetError extends SyncError { throw RealmException("Missing `originalFilePath`"); } - return _app!.handle.immediatelyRunFileActions(originalFilePath!); + return _app.handle.immediatelyRunFileActions(originalFilePath!); } } diff --git a/packages/realm_dart/lib/src/native/app_handle.dart b/packages/realm_dart/lib/src/native/app_handle.dart index 0f26c5c5d..8deb9a74d 100644 --- a/packages/realm_dart/lib/src/native/app_handle.dart +++ b/packages/realm_dart/lib/src/native/app_handle.dart @@ -11,7 +11,6 @@ import 'dart:isolate'; import 'package:ffi/ffi.dart'; import 'package:realm_dart/src/native/convert.dart'; -import '../app.dart'; // TODO: Remove this import import '../init.dart'; import '../logging.dart'; import '../realm_class.dart'; // TODO: Remove this import diff --git a/packages/realm_dart/lib/src/native/list_handle.dart b/packages/realm_dart/lib/src/native/list_handle.dart index 2d515ef57..26ed292c2 100644 --- a/packages/realm_dart/lib/src/native/list_handle.dart +++ b/packages/realm_dart/lib/src/native/list_handle.dart @@ -52,7 +52,7 @@ class ListHandle extends CollectionHandleBase { final outFound = arena(); // TODO: how should this behave for collections - final realmValue = toRealmValue(value, arena); + final realmValue = value.toNative(arena); invokeGetBool( () => realmLib.realm_list_find( pointer, @@ -89,7 +89,7 @@ class ListHandle extends CollectionHandleBase { // TODO: Consider splitting into two methods void addOrUpdateAt(int index, Object? value, bool insert) { using((Arena arena) { - final realmValue = toRealmValue(value, arena); + final realmValue = value.toNative(arena); invokeGetBool(() => (insert ? realmLib.realm_list_insert : realmLib.realm_list_set)(pointer, index, realmValue.ref)); }); } diff --git a/packages/realm_dart/lib/src/native/map_handle.dart b/packages/realm_dart/lib/src/native/map_handle.dart index fabf1c1c3..4a3eeebea 100644 --- a/packages/realm_dart/lib/src/native/map_handle.dart +++ b/packages/realm_dart/lib/src/native/map_handle.dart @@ -30,7 +30,7 @@ class MapHandle extends CollectionHandleBase { bool remove(String key) { return using((Arena arena) { - final keyNative = toRealmValue(key, arena); + final keyNative = key.toNative(arena); final outErased = arena(); invokeGetBool(() => realmLib.realm_dictionary_erase(pointer, keyNative.ref, outErased)); return outErased.value; @@ -40,7 +40,7 @@ class MapHandle extends CollectionHandleBase { // TODO: avoid taking the [realm] parameter Object? find(Realm realm, String key) { return using((Arena arena) { - final keyNative = toRealmValue(key, arena); + final keyNative = key.toNative(arena); final outValue = arena(); final outFound = arena(); invokeGetBool(() => realmLib.realm_dictionary_find(pointer, keyNative.ref, outValue, outFound)); @@ -79,7 +79,7 @@ class MapHandle extends CollectionHandleBase { bool containsKey(String key) { return using((Arena arena) { - final keyNative = toRealmValue(key, arena); + final keyNative = key.toNative(arena); final found = arena(); invokeGetBool(() => realmLib.realm_dictionary_contains_key(pointer, keyNative.ref, found)); return found.value; @@ -89,7 +89,7 @@ class MapHandle extends CollectionHandleBase { int indexOf(Object? value) { return using((Arena arena) { // TODO: how should this behave for collections - final valueNative = toRealmValue(value, arena); + final valueNative = value.toNative(arena); final index = arena(); invokeGetBool(() => realmLib.realm_dictionary_contains_value(pointer, valueNative.ref, index)); return index.value; @@ -100,7 +100,7 @@ class MapHandle extends CollectionHandleBase { ObjectHandle insertEmbedded(String key) { return using((Arena arena) { - final keyNative = toRealmValue(key, arena); + final keyNative = key.toNative(arena); final ptr = invokeGetPointer(() => realmLib.realm_dictionary_insert_embedded(pointer, keyNative.ref)); return ObjectHandle(ptr, root); }); @@ -108,8 +108,8 @@ class MapHandle extends CollectionHandleBase { void insert(String key, Object? value) { using((Arena arena) { - final keyNative = toRealmValue(key, arena); - final valueNative = toRealmValue(value, arena); + final keyNative = key.toNative(arena); + final valueNative = value.toNative(arena); invokeGetBool( () => realmLib.realm_dictionary_insert( pointer, @@ -124,7 +124,7 @@ class MapHandle extends CollectionHandleBase { void insertCollection(Realm realm, String key, RealmValue value) { using((Arena arena) { - final keyNative = toRealmValue(key, arena); + final keyNative = key.toNative(arena); createCollection( realm, value, diff --git a/packages/realm_dart/lib/src/native/object_handle.dart b/packages/realm_dart/lib/src/native/object_handle.dart index 6f8a63f9c..8c2170653 100644 --- a/packages/realm_dart/lib/src/native/object_handle.dart +++ b/packages/realm_dart/lib/src/native/object_handle.dart @@ -59,7 +59,7 @@ class ObjectHandle extends RootedHandleBase { // with setCollection? void setValue(int propertyKey, Object? value, bool isDefault) { using((Arena arena) { - final realmValue = toRealmValue(value, arena); + final realmValue = value.toNative(arena); invokeGetBool( () => realmLib.realm_set_value( pointer, diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 4699144af..e2b8a1641 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -661,15 +661,17 @@ extension StringEx on String { return realmString; } } - -Pointer toRealmValue(Object? value, Allocator allocator) { - final realmValue = allocator(); - if (value is RealmValue && value.type.isCollection) { - throw RealmError( - "Don't use _toPrimitiveValue if the value may contain collections. Use storeValue instead. This is a bug in the Realm Flutter SDK and should be reported to https://github.com/realm/realm-dart/issues/new"); +extension NullableObjectEx on Object? { + Pointer toNative(Allocator allocator) { + final self = this; + final realmValue = allocator(); + if (self is RealmValue && self.type.isCollection) { + throw RealmError( + "Don't use _toPrimitiveValue if the value may contain collections. Use storeValue instead. This is a bug in the Realm Flutter SDK and should be reported to https://github.com/realm/realm-dart/issues/new"); + } + _intoRealmValue(self, realmValue.ref, allocator); + return realmValue; } - intoRealmValue(value, realmValue.ref, allocator); - return realmValue; } const int _microsecondsPerSecond = 1000 * 1000; @@ -682,28 +684,28 @@ void intoRealmQueryArg(Object? value, Pointer realmQueryArg, realmQueryArg.ref.arg = allocator(value.length); int i = 0; for (var item in value) { - intoRealmValue(item, realmQueryArg.ref.arg[i], allocator); + _intoRealmValue(item, realmQueryArg.ref.arg[i], allocator); i++; } } else { realmQueryArg.ref.arg = allocator(); realmQueryArg.ref.nb_args = 1; realmQueryArg.ref.is_list = false; - intoRealmValueHack(value, realmQueryArg.ref.arg.ref, allocator); + _intoRealmValueHack(value, realmQueryArg.ref.arg.ref, allocator); } } -void intoRealmValueHack(Object? value, realm_value realmValue, Allocator allocator) { +void _intoRealmValueHack(Object? value, realm_value realmValue, Allocator allocator) { if (value is GeoShape) { - intoRealmValue(value.toString(), realmValue, allocator); + _intoRealmValue(value.toString(), realmValue, allocator); } else if (value is RealmValueType) { - intoRealmValue(value.toQueryArgString(), realmValue, allocator); + _intoRealmValue(value.toQueryArgString(), realmValue, allocator); } else { - intoRealmValue(value, realmValue, allocator); + _intoRealmValue(value, realmValue, allocator); } } -void intoRealmValue(Object? value, realm_value realmValue, Allocator allocator) { +void _intoRealmValue(Object? value, realm_value realmValue, Allocator allocator) { if (value == null) { realmValue.type = realm_value_type.RLM_TYPE_NULL; } else if (value is RealmObjectBase) { @@ -766,7 +768,7 @@ void intoRealmValue(Object? value, realm_value realmValue, Allocator allocator) } else if (value.type == Map) { realmValue.type = realm_value_type.RLM_TYPE_DICTIONARY; } else { - return intoRealmValue(value.value, realmValue, allocator); + return _intoRealmValue(value.value, realmValue, allocator); } } else { throw RealmException("Property type ${value.runtimeType} not supported"); diff --git a/packages/realm_dart/lib/src/native/realm_handle.dart b/packages/realm_dart/lib/src/native/realm_handle.dart index a55b28810..1467cceea 100644 --- a/packages/realm_dart/lib/src/native/realm_handle.dart +++ b/packages/realm_dart/lib/src/native/realm_handle.dart @@ -65,7 +65,7 @@ class RealmHandle extends HandleBase { ObjectHandle createWithPrimaryKey(int classKey, Object? primaryKey) { return using((Arena arena) { - final realmValue = toRealmValue(primaryKey, arena); + final realmValue = primaryKey.toNative(arena); final realmPtr = invokeGetPointer(() => realmLib.realm_object_create_with_primary_key(pointer, classKey, realmValue.ref)); return ObjectHandle(realmPtr, this); }); @@ -78,7 +78,7 @@ class RealmHandle extends HandleBase { ObjectHandle getOrCreateWithPrimaryKey(int classKey, Object? primaryKey) { return using((Arena arena) { - final realmValue = toRealmValue(primaryKey, arena); + final realmValue = primaryKey.toNative(arena); final didCreate = arena(); final realmPtr = invokeGetPointer(() => realmLib.realm_object_get_or_create_with_primary_key( pointer, @@ -275,7 +275,7 @@ class RealmHandle extends HandleBase { ObjectHandle? find(int classKey, Object? primaryKey) { return using((Arena arena) { - final realmValue = toRealmValue(primaryKey, arena); + final realmValue = primaryKey.toNative(arena); final ptr = realmLib.realm_object_find_with_primary_key(pointer, classKey, realmValue.ref, nullptr); if (ptr == nullptr) { return null; diff --git a/packages/realm_dart/lib/src/native/results_handle.dart b/packages/realm_dart/lib/src/native/results_handle.dart index d43e80c29..a08406ddb 100644 --- a/packages/realm_dart/lib/src/native/results_handle.dart +++ b/packages/realm_dart/lib/src/native/results_handle.dart @@ -45,7 +45,7 @@ class ResultsHandle extends RootedHandleBase { final outFound = arena(); // TODO: how should this behave for collections - final realmValue = toRealmValue(value, arena); + final realmValue = value.toNative(arena); invokeGetBool( () => realmLib.realm_results_find( pointer, diff --git a/packages/realm_dart/lib/src/native/set_handle.dart b/packages/realm_dart/lib/src/native/set_handle.dart index f2cdcf724..7ad0e317b 100644 --- a/packages/realm_dart/lib/src/native/set_handle.dart +++ b/packages/realm_dart/lib/src/native/set_handle.dart @@ -46,7 +46,7 @@ class SetHandle extends RootedHandleBase { bool insert(Object? value) { return using((Arena arena) { - final realmValue = toRealmValue(value, arena); + final realmValue = value.toNative(arena); final outIndex = arena(); final outInserted = arena(); invokeGetBool(() => realmLib.realm_set_insert(pointer, realmValue.ref, outIndex, outInserted)); @@ -71,7 +71,7 @@ class SetHandle extends RootedHandleBase { bool find(Object? value) { return using((Arena arena) { // TODO: how should this behave for collections - final realmValue = toRealmValue(value, arena); + final realmValue = value.toNative(arena); final outIndex = arena(); final outFound = arena(); invokeGetBool(() => realmLib.realm_set_find(pointer, realmValue.ref, outIndex, outFound)); @@ -82,7 +82,7 @@ class SetHandle extends RootedHandleBase { bool remove(Object? value) { return using((Arena arena) { // TODO: do we support sets containing mixed collections - final realmValue = toRealmValue(value, arena); + final realmValue = value.toNative(arena); final outErased = arena(); invokeGetBool(() => realmLib.realm_set_erase(pointer, realmValue.ref, outErased)); return outErased.value; diff --git a/packages/realm_dart/lib/src/native/subscription_set_handle.dart b/packages/realm_dart/lib/src/native/subscription_set_handle.dart index cdb675e29..eebebd5f7 100644 --- a/packages/realm_dart/lib/src/native/subscription_set_handle.dart +++ b/packages/realm_dart/lib/src/native/subscription_set_handle.dart @@ -9,7 +9,6 @@ import 'package:realm_dart/src/native/convert.dart'; import '../realm_dart.dart'; import '../scheduler.dart'; -import '../subscription.dart'; import 'error_handling.dart'; import 'mutable_subscription_set_handle.dart'; import 'realm_bindings.dart'; From 082686f5099fc42bbbd811ca9838524d8019b462 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Thu, 25 Apr 2024 22:35:30 +0200 Subject: [PATCH 51/68] Replace last use of deprecated Pointer.elementAt(i) --- .../realm_dart/lib/src/native/realm_core.dart | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index e2b8a1641..80cd53575 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -268,7 +268,7 @@ class _RealmCore { static late final _RealmCore _instance; _RealmCore() { - // This disables creation of a second _RealmCore instance effectivelly making `realmCore` global variable readonly + // This disables creation of a second _RealmCore instance effectively making `realmCore` global variable readonly _instance = this; // This prevents reentrance if `realmCore` global variable is accessed during _RealmCore construction @@ -370,7 +370,7 @@ class _RealmCore { final schemas = []; for (var i = 0; i < actualCount.value; i++) { final classInfo = arena(); - final classKey = classesPtr.elementAt(i).value; + final classKey = (classesPtr + i).value; invokeGetBool(() => realmLib.realm_get_class(realm.pointer, classKey, classInfo)); final name = classInfo.ref.name.cast().toDartString(); @@ -397,7 +397,7 @@ class _RealmCore { final result = []; for (var i = 0; i < actualCount.value; i++) { - final property = propertiesPtr.elementAt(i).ref.toSchemaProperty(); + final property = (propertiesPtr + i).ref.toSchemaProperty(); result.add(property); } @@ -460,7 +460,7 @@ class _RealmCore { propertyCount = propertyCountPtr.value; Map result = {}; for (var i = 0; i < propertyCount; i++) { - final property = propertiesPtr.elementAt(i); + final property = propertiesPtr + i; final propertyName = property.ref.name.cast().toRealmDartString()!; final objectType = property.ref.link_target.cast().toRealmDartString(treatEmptyAsNull: true); final linkOriginProperty = property.ref.link_origin_property_name.cast().toRealmDartString(treatEmptyAsNull: true); @@ -661,6 +661,7 @@ extension StringEx on String { return realmString; } } + extension NullableObjectEx on Object? { Pointer toNative(Allocator allocator) { final self = this; @@ -763,9 +764,9 @@ void _intoRealmValue(Object? value, realm_value realmValue, Allocator allocator) realmValue.values.binary.data = allocator(value.length); realmValue.values.binary.data.asTypedList(value.length).setAll(0, value); } else if (value is RealmValue) { - if (value.type == List) { + if (value is List) { realmValue.type = realm_value_type.RLM_TYPE_LIST; - } else if (value.type == Map) { + } else if (value is Map) { realmValue.type = realm_value_type.RLM_TYPE_DICTIONARY; } else { return _intoRealmValue(value.value, realmValue, allocator); @@ -786,7 +787,7 @@ extension PointerRealmValueEx on Pointer { List toStringList(int count) { final result = List.filled(count, ''); for (var i = 0; i < count; i++) { - final strValue = elementAt(i).ref.values.string; + final strValue = (this + i).ref.values.string; result[i] = strValue.data.cast().toRealmDartString(length: strValue.size)!; } @@ -817,7 +818,7 @@ extension RealmValueEx on realm_value_t { } final objectKey = values.link.target; final classKey = values.link.target_table; - if (realm.metadata.getByClassKeyIfExists(classKey) == null) return null; // temprorary workaround to avoid crash on assertion + if (realm.metadata.getByClassKeyIfExists(classKey) == null) return null; // temporary workaround to avoid crash on assertion return realm.handle.getObject(classKey, objectKey); case realm_value_type.RLM_TYPE_BINARY: return Uint8List.fromList(values.binary.data.asTypedList(values.binary.size)); @@ -868,9 +869,9 @@ extension ArrayUint8Ex on Array { extension PointerSizeEx on Pointer { List toIntList(int count) { - List result = List.filled(count, elementAt(0).value); + List result = List.filled(count, value); for (var i = 1; i < count; i++) { - result[i] = elementAt(i).value; + result[i] = (this + i).value; } return result; } From bfefe186eb9c8439b6fa60392672590ee8dd39a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Fri, 26 Apr 2024 11:14:22 +0200 Subject: [PATCH 52/68] More RealmHandle stuff --- .../realm_dart/lib/src/native/realm_core.dart | 115 +----------------- .../lib/src/native/realm_handle.dart | 115 ++++++++++++++++++ 2 files changed, 118 insertions(+), 112 deletions(-) diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 80cd53575..d28c989a7 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -13,7 +13,6 @@ import 'package:crypto/crypto.dart'; import 'package:ffi/ffi.dart' hide StringUtf8Pointer, StringUtf16Pointer; import 'package:path/path.dart' as path; import 'package:pubspec_parse/pubspec_parse.dart'; -import 'package:realm_common/realm_common.dart' hide Decimal128; import '../app.dart'; import '../configuration.dart'; @@ -352,72 +351,7 @@ class _RealmCore { return AsyncOpenTaskProgressNotificationTokenHandle(tokenPtr); } - RealmSchema readSchema(Realm realm) { - return using((Arena arena) { - return _readSchema(realm.handle, arena); - }); - } - - RealmSchema _readSchema(RealmHandle realm, Arena arena, {int expectedSize = 10}) { - final classesPtr = arena(expectedSize); - final actualCount = arena(); - invokeGetBool(() => realmLib.realm_get_class_keys(realm.pointer, classesPtr, expectedSize, actualCount)); - if (expectedSize < actualCount.value) { - arena.free(classesPtr); - return _readSchema(realm, arena, expectedSize: actualCount.value); - } - - final schemas = []; - for (var i = 0; i < actualCount.value; i++) { - final classInfo = arena(); - final classKey = (classesPtr + i).value; - invokeGetBool(() => realmLib.realm_get_class(realm.pointer, classKey, classInfo)); - - final name = classInfo.ref.name.cast().toDartString(); - final baseType = ObjectType.values.firstWhere((element) => element.flags == classInfo.ref.flags, - orElse: () => throw RealmError('No object type found for flags ${classInfo.ref.flags}')); - final schema = - _getSchemaForClassKey(realm, classKey, name, baseType, arena, expectedSize: classInfo.ref.num_properties + classInfo.ref.num_computed_properties); - schemas.add(schema); - } - - return RealmSchema(schemas); - } - - SchemaObject _getSchemaForClassKey(RealmHandle realm, int classKey, String name, ObjectType baseType, Arena arena, {int expectedSize = 10}) { - final actualCount = arena(); - final propertiesPtr = arena(expectedSize); - invokeGetBool(() => realmLib.realm_get_class_properties(realm.pointer, classKey, propertiesPtr, expectedSize, actualCount)); - - if (expectedSize < actualCount.value) { - // The supplied array was too small - resize it - arena.free(propertiesPtr); - return _getSchemaForClassKey(realm, classKey, name, baseType, arena, expectedSize: actualCount.value); - } - - final result = []; - for (var i = 0; i < actualCount.value; i++) { - final property = (propertiesPtr + i).ref.toSchemaProperty(); - result.add(property); - } - - late Type type; - switch (baseType) { - case ObjectType.realmObject: - type = RealmObject; - break; - case ObjectType.embeddedObject: - type = EmbeddedObject; - break; - case ObjectType.asymmetricObject: - type = AsymmetricObject; - break; - default: - throw RealmError('$baseType is not supported yet'); - } - - return SchemaObject(baseType, type, name, result); - } + RealmSchema readSchema(Realm realm) => realm.handle.readSchema(); void deleteRealmFiles(String path) { using((Arena arena) { @@ -426,52 +360,9 @@ class _RealmCore { }); } - RealmObjectMetadata getObjectMetadata(Realm realm, SchemaObject schema) { - return using((Arena arena) { - final found = arena(); - final classInfo = arena(); - invokeGetBool(() => realmLib.realm_find_class(realm.handle.pointer, schema.name.toCharPtr(arena), found, classInfo), - "Error getting class ${schema.name} from realm at ${realm.config.path}"); - - if (!found.value) { - throwLastError("Class ${schema.name} not found in ${realm.config.path}"); - } - - final primaryKey = classInfo.ref.primary_key.cast().toRealmDartString(treatEmptyAsNull: true); - return RealmObjectMetadata(schema, classInfo.ref.key, _getPropertiesMetadata(realm, classInfo.ref.key, primaryKey, arena)); - }); - } - - Map getPropertiesMetadata(Realm realm, int classKey, String? primaryKeyName) { - return using((Arena arena) { - return _getPropertiesMetadata(realm, classKey, primaryKeyName, arena); - }); - } + RealmObjectMetadata getObjectMetadata(Realm realm, SchemaObject schema) => realm.handle.getObjectMetadata(schema); - Map _getPropertiesMetadata(Realm realm, int classKey, String? primaryKeyName, Arena arena) { - final propertyCountPtr = arena(); - invokeGetBool(() => realmLib.realm_get_property_keys(realm.handle.pointer, classKey, nullptr, 0, propertyCountPtr), "Error getting property count"); - - var propertyCount = propertyCountPtr.value; - final propertiesPtr = arena(propertyCount); - invokeGetBool(() => realmLib.realm_get_class_properties(realm.handle.pointer, classKey, propertiesPtr, propertyCount, propertyCountPtr), - "Error getting class properties."); - - propertyCount = propertyCountPtr.value; - Map result = {}; - for (var i = 0; i < propertyCount; i++) { - final property = propertiesPtr + i; - final propertyName = property.ref.name.cast().toRealmDartString()!; - final objectType = property.ref.link_target.cast().toRealmDartString(treatEmptyAsNull: true); - final linkOriginProperty = property.ref.link_origin_property_name.cast().toRealmDartString(treatEmptyAsNull: true); - final isNullable = property.ref.flags & realm_property_flags.RLM_PROPERTY_NULLABLE != 0; - final isPrimaryKey = propertyName == primaryKeyName; - final propertyMeta = RealmPropertyMetadata(property.ref.key, objectType, linkOriginProperty, RealmPropertyType.values.elementAt(property.ref.type), - isNullable, isPrimaryKey, RealmCollectionType.values.elementAt(property.ref.collection_type)); - result[propertyName] = propertyMeta; - } - return result; - } + Map getPropertiesMetadata(Realm realm, int classKey, String? primaryKeyName) => realm.handle.getPropertiesMetadata(classKey, primaryKeyName); // For debugging // ignore: unused_element diff --git a/packages/realm_dart/lib/src/native/realm_handle.dart b/packages/realm_dart/lib/src/native/realm_handle.dart index 1467cceea..2636c894e 100644 --- a/packages/realm_dart/lib/src/native/realm_handle.dart +++ b/packages/realm_dart/lib/src/native/realm_handle.dart @@ -6,9 +6,11 @@ import 'dart:ffi'; import 'package:cancellation_token/cancellation_token.dart'; import 'package:ffi/ffi.dart'; +import 'package:realm_common/realm_common.dart'; import '../logging.dart'; import '../realm_class.dart'; +import '../realm_object.dart'; import 'config_handle.dart'; import 'convert.dart'; import 'error_handling.dart'; @@ -321,6 +323,119 @@ class RealmHandle extends HandleBase { ); return CallbackTokenHandle(ptr, this); } + + RealmSchema readSchema() { + return using((Arena arena) { + return _readSchema(arena); + }); + } + + RealmSchema _readSchema(Arena arena, {int expectedSize = 10}) { + final classesPtr = arena(expectedSize); + final actualCount = arena(); + invokeGetBool(() => realmLib.realm_get_class_keys(pointer, classesPtr, expectedSize, actualCount)); + if (expectedSize < actualCount.value) { + arena.free(classesPtr); + return _readSchema(arena, expectedSize: actualCount.value); + } + + final schemas = []; + for (var i = 0; i < actualCount.value; i++) { + final classInfo = arena(); + final classKey = (classesPtr + i).value; + invokeGetBool(() => realmLib.realm_get_class(pointer, classKey, classInfo)); + + final name = classInfo.ref.name.cast().toDartString(); + final baseType = ObjectType.values.firstWhere((element) => element.flags == classInfo.ref.flags, + orElse: () => throw RealmError('No object type found for flags ${classInfo.ref.flags}')); + final schema = _getSchemaForClassKey(classKey, name, baseType, arena, expectedSize: classInfo.ref.num_properties + classInfo.ref.num_computed_properties); + schemas.add(schema); + } + + return RealmSchema(schemas); + } + + SchemaObject _getSchemaForClassKey(int classKey, String name, ObjectType baseType, Arena arena, {int expectedSize = 10}) { + final actualCount = arena(); + final propertiesPtr = arena(expectedSize); + invokeGetBool(() => realmLib.realm_get_class_properties(pointer, classKey, propertiesPtr, expectedSize, actualCount)); + + if (expectedSize < actualCount.value) { + // The supplied array was too small - resize it + arena.free(propertiesPtr); + return _getSchemaForClassKey(classKey, name, baseType, arena, expectedSize: actualCount.value); + } + + final result = []; + for (var i = 0; i < actualCount.value; i++) { + final property = (propertiesPtr + i).ref.toSchemaProperty(); + result.add(property); + } + + late Type type; + switch (baseType) { + case ObjectType.realmObject: + type = RealmObject; + break; + case ObjectType.embeddedObject: + type = EmbeddedObject; + break; + case ObjectType.asymmetricObject: + type = AsymmetricObject; + break; + default: + throw RealmError('$baseType is not supported yet'); + } + + return SchemaObject(baseType, type, name, result); + } + + Map getPropertiesMetadata(int classKey, String? primaryKeyName) { + return using((Arena arena) { + return _getPropertiesMetadata(classKey, primaryKeyName, arena); + }); + } + + RealmObjectMetadata getObjectMetadata(SchemaObject schema) { + return using((Arena arena) { + final found = arena(); + final classInfo = arena(); + invokeGetBool(() => realmLib.realm_find_class(pointer, schema.name.toCharPtr(arena), found, classInfo)); + // "Error getting class ${schema.name} from realm at ${realm.config.path}"); + + if (!found.value) { + throwLastError(); //"Class ${schema.name} not found in ${realm.config.path}"); + } + + final primaryKey = classInfo.ref.primary_key.cast().toRealmDartString(treatEmptyAsNull: true); + return RealmObjectMetadata(schema, classInfo.ref.key, _getPropertiesMetadata(classInfo.ref.key, primaryKey, arena)); + }); + } + + Map _getPropertiesMetadata(int classKey, String? primaryKeyName, Arena arena) { + final propertyCountPtr = arena(); + invokeGetBool(() => realmLib.realm_get_property_keys(pointer, classKey, nullptr, 0, propertyCountPtr), "Error getting property count"); + + var propertyCount = propertyCountPtr.value; + final propertiesPtr = arena(propertyCount); + invokeGetBool( + () => realmLib.realm_get_class_properties(pointer, classKey, propertiesPtr, propertyCount, propertyCountPtr), "Error getting class properties."); + + propertyCount = propertyCountPtr.value; + Map result = {}; + for (var i = 0; i < propertyCount; i++) { + final property = propertiesPtr + i; + final propertyName = property.ref.name.cast().toRealmDartString()!; + final objectType = property.ref.link_target.cast().toRealmDartString(treatEmptyAsNull: true); + final linkOriginProperty = property.ref.link_origin_property_name.cast().toRealmDartString(treatEmptyAsNull: true); + final isNullable = property.ref.flags & realm_property_flags.RLM_PROPERTY_NULLABLE != 0; + final isPrimaryKey = propertyName == primaryKeyName; + final propertyMeta = RealmPropertyMetadata(property.ref.key, objectType, linkOriginProperty, RealmPropertyType.values.elementAt(property.ref.type), + isNullable, isPrimaryKey, RealmCollectionType.values.elementAt(property.ref.collection_type)); + result[propertyName] = propertyMeta; + } + return result; + } } class CallbackTokenHandle extends RootedHandleBase { From ef6774344abccd9def31ac60ec07bf0e179b8ee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Fri, 26 Apr 2024 15:40:36 +0200 Subject: [PATCH 53/68] Replace invokeGetBool and invokeGetPointer --- .../realm_dart/lib/src/native/app_handle.dart | 163 ++++++++---------- .../lib/src/native/config_handle.dart | 4 +- .../lib/src/native/credentials_handle.dart | 30 ++-- .../lib/src/native/error_handling.dart | 19 +- .../lib/src/native/list_handle.dart | 66 +++---- .../realm_dart/lib/src/native/map_handle.dart | 60 +++---- .../mutable_subscription_set_handle.dart | 64 +++---- .../lib/src/native/object_handle.dart | 42 ++--- .../lib/src/native/query_handle.dart | 2 +- .../realm_dart/lib/src/native/realm_core.dart | 24 +-- .../lib/src/native/realm_handle.dart | 123 +++++++------ .../lib/src/native/results_handle.dart | 64 +++---- .../lib/src/native/schema_handle.dart | 2 +- .../lib/src/native/session_handle.dart | 27 ++- .../realm_dart/lib/src/native/set_handle.dart | 40 +++-- .../src/native/subscription_set_handle.dart | 7 +- .../lib/src/native/user_handle.dart | 53 +++--- 17 files changed, 391 insertions(+), 399 deletions(-) diff --git a/packages/realm_dart/lib/src/native/app_handle.dart b/packages/realm_dart/lib/src/native/app_handle.dart index 8deb9a74d..80efaa44c 100644 --- a/packages/realm_dart/lib/src/native/app_handle.dart +++ b/packages/realm_dart/lib/src/native/app_handle.dart @@ -1,7 +1,6 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 - import 'dart:async'; import 'dart:convert'; import 'dart:ffi'; @@ -9,12 +8,12 @@ import 'dart:io'; import 'dart:isolate'; import 'package:ffi/ffi.dart'; -import 'package:realm_dart/src/native/convert.dart'; import '../init.dart'; import '../logging.dart'; import '../realm_class.dart'; // TODO: Remove this import import '../scheduler.dart'; +import 'convert.dart'; import 'credentials_handle.dart'; import 'error_handling.dart'; import 'handle_base.dart'; @@ -36,9 +35,8 @@ class AppHandle extends HandleBase { } final httpTransportHandle = _createHttpTransport(configuration.httpClient); final appConfigHandle = _createAppConfig(configuration, httpTransportHandle); - final syncClientConfigHandle = _createSyncClientConfig(configuration); - final realmAppPtr = invokeGetPointer(() => realmLib.realm_app_create_cached(appConfigHandle.pointer, syncClientConfigHandle.pointer)); - return AppHandle(realmAppPtr); + final appPtr = realmLib.realm_app_create_cached(appConfigHandle.pointer).raiseIfNull(); + return AppHandle(appPtr); } UserHandle? get currentUser { @@ -50,7 +48,7 @@ class AppHandle extends HandleBase { List _getUsers(Arena arena, {int expectedSize = 2}) { final actualCount = arena(); final usersPtr = arena>(expectedSize); - invokeGetBool(() => realmLib.realm_app_get_all_users(pointer, usersPtr, expectedSize, actualCount)); + realmLib.realm_app_get_all_users(pointer, usersPtr, expectedSize, actualCount).raiseIfFalse(); if (expectedSize < actualCount.value) { // The supplied array was too small - resize it @@ -68,29 +66,23 @@ class AppHandle extends HandleBase { Future removeUser(UserHandle user) { final completer = Completer(); - invokeGetBool( - () => realmLib.realm_app_remove_user( + realmLib.realm_app_remove_user( pointer, user.pointer, realmLib.addresses.realm_dart_void_completion_callback, createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - ), - "Remove user failed", - ); + ).raiseIfFalse("Remove user failed"); return completer.future; } void switchUser(UserHandle user) { using((arena) { - invokeGetBool( - () => realmLib.realm_app_switch_user( + realmLib.realm_app_switch_user( pointer, user.pointer, nullptr, - ), - "Switch user failed", - ); + ).raiseIfFalse("Switch user failed"); }); } @@ -104,32 +96,26 @@ class AppHandle extends HandleBase { Future updateBaseUrl(Uri? baseUrl) { final completer = Completer(); using((arena) { - invokeGetBool( - () => realmLib.realm_app_update_base_url( + realmLib.realm_app_update_base_url( pointer, baseUrl.toString().toCharPtr(arena), realmLib.addresses.realm_dart_void_completion_callback, createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - ), - "Update base URL failed", - ); + ).raiseIfFalse("Update base URL failed"); }); return completer.future; } Future refreshCustomData(UserHandle user) { final completer = Completer(); - invokeGetBool( - () => realmLib.realm_app_refresh_custom_data( + realmLib.realm_app_refresh_custom_data( pointer, user.pointer, realmLib.addresses.realm_dart_void_completion_callback, createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - ), - "Refresh custom data failed", - ); + ).raiseIfFalse("Refresh custom data failed"); return completer.future; } @@ -139,32 +125,27 @@ class AppHandle extends HandleBase { Future logIn(CredentialsHandle credentials) async { final completer = Completer(); - invokeGetBool( - () => realmLib.realm_app_log_in_with_credentials( + realmLib.realm_app_log_in_with_credentials( pointer, credentials.pointer, realmLib.addresses.realm_dart_user_completion_callback, createAsyncUserCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - ), - "Login failed", - ); + ).raiseIfFalse("Login failed"); return await completer.future; } Future registerUser(String email, String password) { final completer = Completer(); using((arena) { - invokeGetBool( - () => realmLib.realm_app_email_password_provider_client_register_email( + realmLib.realm_app_email_password_provider_client_register_email( pointer, email.toCharPtr(arena), password.toRealmString(arena).ref, realmLib.addresses.realm_dart_void_completion_callback, createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - ), - ); + ).raiseIfFalse(); }); return completer.future; } @@ -172,16 +153,14 @@ class AppHandle extends HandleBase { Future confirmUser(String token, String tokenId) async { final completer = Completer(); using((arena) { - invokeGetBool( - () => realmLib.realm_app_email_password_provider_client_confirm_user( + realmLib.realm_app_email_password_provider_client_confirm_user( pointer, token.toCharPtr(arena), tokenId.toCharPtr(arena), realmLib.addresses.realm_dart_void_completion_callback, createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - ), - ); + ).raiseIfFalse(); }); return await completer.future; } @@ -189,15 +168,13 @@ class AppHandle extends HandleBase { Future resendConfirmation(String email) { final completer = Completer(); using((arena) { - invokeGetBool( - () => realmLib.realm_app_email_password_provider_client_resend_confirmation_email( + realmLib.realm_app_email_password_provider_client_resend_confirmation_email( pointer, email.toCharPtr(arena), realmLib.addresses.realm_dart_void_completion_callback, createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - ), - ); + ).raiseIfFalse(); }); return completer.future; } @@ -205,8 +182,7 @@ class AppHandle extends HandleBase { Future completeResetPassword(String password, String token, String tokenId) { final completer = Completer(); using((arena) { - invokeGetBool( - () => realmLib.realm_app_email_password_provider_client_reset_password( + realmLib.realm_app_email_password_provider_client_reset_password( pointer, password.toRealmString(arena).ref, token.toCharPtr(arena), @@ -214,8 +190,7 @@ class AppHandle extends HandleBase { realmLib.addresses.realm_dart_void_completion_callback, createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - ), - ); + ).raiseIfFalse(); }); return completer.future; } @@ -223,15 +198,13 @@ class AppHandle extends HandleBase { Future requestResetPassword(String email) { final completer = Completer(); using((arena) { - invokeGetBool( - () => realmLib.realm_app_email_password_provider_client_send_reset_password_email( + realmLib.realm_app_email_password_provider_client_send_reset_password_email( pointer, email.toCharPtr(arena), realmLib.addresses.realm_dart_void_completion_callback, createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - ), - ); + ).raiseIfFalse(); }); return completer.future; } @@ -239,8 +212,7 @@ class AppHandle extends HandleBase { Future callResetPasswordFunction(String email, String password, String? argsAsJSON) { final completer = Completer(); using((arena) { - invokeGetBool( - () => realmLib.realm_app_email_password_provider_client_call_reset_password_function( + realmLib.realm_app_email_password_provider_client_call_reset_password_function( pointer, email.toCharPtr(arena), password.toRealmString(arena).ref, @@ -248,8 +220,7 @@ class AppHandle extends HandleBase { realmLib.addresses.realm_dart_void_completion_callback, createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - ), - ); + ).raiseIfFalse(); }); return completer.future; } @@ -257,15 +228,13 @@ class AppHandle extends HandleBase { Future retryCustomConfirmationFunction(String email) { final completer = Completer(); using((arena) { - invokeGetBool( - () => realmLib.realm_app_email_password_provider_client_retry_custom_confirmation( + realmLib.realm_app_email_password_provider_client_retry_custom_confirmation( pointer, email.toCharPtr(arena), realmLib.addresses.realm_dart_void_completion_callback, createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - ), - ); + ).raiseIfFalse(); }); return completer.future; } @@ -273,59 +242,64 @@ class AppHandle extends HandleBase { Future logOut(UserHandle? user) { final completer = Completer(); if (user == null) { - invokeGetBool( - () => realmLib.realm_app_log_out_current_user( + realmLib.realm_app_log_out_current_user( pointer, realmLib.addresses.realm_dart_void_completion_callback, createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - ), - "Logout failed", - ); + ).raiseIfFalse("Logout failed"); } else { - invokeGetBool( - () => realmLib.realm_app_log_out( + realmLib.realm_app_log_out( pointer, user.pointer, realmLib.addresses.realm_dart_void_completion_callback, createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - ), - "Logout failed", - ); + ).raiseIfFalse("Logout failed"); } return completer.future; } Future deleteUser(UserHandle user) { final completer = Completer(); - invokeGetBool( - () => realmLib.realm_app_delete_user( + realmLib.realm_app_delete_user( pointer, user.pointer, realmLib.addresses.realm_dart_void_completion_callback, createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - ), - "Delete user failed", - ); + ).raiseIfFalse("Delete user failed"); return completer.future; } bool immediatelyRunFileActions(String realmPath) { return using((arena) { final didRun = arena(); - invokeGetBool( - () => realmLib.realm_sync_immediately_run_file_actions( + realmLib.realm_sync_immediately_run_file_actions( pointer, realmPath.toCharPtr(arena), didRun, - ), - "An error occurred while resetting the Realm. Check if the file is in use: '$realmPath'", - ); + ).raiseIfFalse("An error occurred while resetting the Realm. Check if the file is in use: '$realmPath'"); return didRun.value; }); } + + Future callAppFunction(UserHandle user, String functionName, String? argsAsJSON) { + return using((arena) { + final completer = Completer(); + realmLib.realm_app_call_function( + pointer, + user.pointer, + functionName.toCharPtr(arena), + argsAsJSON?.toCharPtr(arena) ?? nullptr, + nullptr, + realmLib.addresses.realm_dart_return_string_callback, + createAsyncFunctionCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ).raiseIfFalse(); + return completer.future; + }); + } } // TODO: @@ -474,22 +448,21 @@ Future _requestCallbackAsync( }); } -class _SyncClientConfigHandle extends HandleBase { - _SyncClientConfigHandle(Pointer pointer) : super(pointer, 8); -} - -_SyncClientConfigHandle _createSyncClientConfig(AppConfiguration configuration) { - return using((arena) { - final handle = _SyncClientConfigHandle(realmLib.realm_sync_client_config_new()); - - realmLib.realm_sync_client_config_set_base_file_path(handle.pointer, configuration.baseFilePath.path.toCharPtr(arena)); - realmLib.realm_sync_client_config_set_metadata_mode(handle.pointer, configuration.metadataPersistenceMode.index); - realmLib.realm_sync_client_config_set_connect_timeout(handle.pointer, configuration.maxConnectionTimeout.inMilliseconds); - if (configuration.metadataEncryptionKey != null && configuration.metadataPersistenceMode == MetadataPersistenceMode.encrypted) { - realmLib.realm_sync_client_config_set_metadata_encryption_key(handle.pointer, configuration.metadataEncryptionKey!.toUint8Ptr(arena)); - } - return handle; - }); +Pointer createAsyncFunctionCallbackUserdata(Completer completer) { + final callback = Pointer.fromFunction< + Void Function( + Pointer, + Pointer, + Pointer, + )>(callAppFunctionCallback); + + final userdata = realmLib.realm_dart_userdata_async_new( + completer, + callback.cast(), + scheduler.handle.pointer, + ); + + return userdata.cast(); } class _AppConfigHandle extends HandleBase { diff --git a/packages/realm_dart/lib/src/native/config_handle.dart b/packages/realm_dart/lib/src/native/config_handle.dart index 4b7647d81..27fd40d51 100644 --- a/packages/realm_dart/lib/src/native/config_handle.dart +++ b/packages/realm_dart/lib/src/native/config_handle.dart @@ -88,7 +88,7 @@ class ConfigHandle extends HandleBase { realmLib.realm_config_set_in_memory(configHandle.pointer, true); } else if (config is FlexibleSyncConfiguration) { realmLib.realm_config_set_schema_mode(configHandle.pointer, realm_schema_mode.RLM_SCHEMA_MODE_ADDITIVE_DISCOVERED); - final syncConfigPtr = invokeGetPointer(() => realmLib.realm_flx_sync_config_new(config.user.handle.pointer)); + final syncConfigPtr = realmLib.realm_flx_sync_config_new(config.user.handle.pointer).raiseIfNull(); try { realmLib.realm_sync_config_set_session_stop_policy(syncConfigPtr, config.sessionStopPolicy.index); realmLib.realm_sync_config_set_resync_mode(syncConfigPtr, config.clientResetHandler.clientResyncMode.index); @@ -159,7 +159,7 @@ void _syncAfterResetCallback(Object userdata, Pointer beforeHandle } final beforeRealm = RealmInternal.getUnowned(syncConfig, RealmHandle.unowned(beforeHandle)); - final realmPtr = invokeGetPointer(() => realmLib.realm_from_thread_safe_reference(afterReference, scheduler.handle.pointer)); + final realmPtr = realmLib.realm_from_thread_safe_reference(afterReference, scheduler.handle.pointer).raiseIfNull(); final afterRealm = RealmInternal.getUnowned(syncConfig, RealmHandle.unowned(realmPtr)); try { diff --git a/packages/realm_dart/lib/src/native/credentials_handle.dart b/packages/realm_dart/lib/src/native/credentials_handle.dart index 94e2e1a1f..9feb3b975 100644 --- a/packages/realm_dart/lib/src/native/credentials_handle.dart +++ b/packages/realm_dart/lib/src/native/credentials_handle.dart @@ -13,59 +13,68 @@ import 'realm_core.dart'; // TODO: Remove this import import 'realm_library.dart'; class CredentialsHandle extends HandleBase { - CredentialsHandle(Pointer pointer) : super(pointer, 16); + CredentialsHandle(Pointer pointer) + : super(pointer, 16); factory CredentialsHandle.anonymous(bool reuseCredentials) { - return CredentialsHandle(realmLib.realm_app_credentials_new_anonymous(reuseCredentials)); + return CredentialsHandle( + realmLib.realm_app_credentials_new_anonymous(reuseCredentials)); } factory CredentialsHandle.emailPassword(String email, String password) { return using((arena) { final emailPtr = email.toCharPtr(arena); final passwordPtr = password.toRealmString(arena); - return CredentialsHandle(realmLib.realm_app_credentials_new_email_password(emailPtr, passwordPtr.ref)); + return CredentialsHandle(realmLib + .realm_app_credentials_new_email_password(emailPtr, passwordPtr.ref)); }); } factory CredentialsHandle.jwt(String token) { return using((arena) { final tokenPtr = token.toCharPtr(arena); - return CredentialsHandle(realmLib.realm_app_credentials_new_jwt(tokenPtr)); + return CredentialsHandle( + realmLib.realm_app_credentials_new_jwt(tokenPtr)); }); } factory CredentialsHandle.apple(String idToken) { return using((arena) { final idTokenPtr = idToken.toCharPtr(arena); - return CredentialsHandle(realmLib.realm_app_credentials_new_apple(idTokenPtr)); + return CredentialsHandle( + realmLib.realm_app_credentials_new_apple(idTokenPtr)); }); } factory CredentialsHandle.facebook(String accessToken) { return using((arena) { final accessTokenPtr = accessToken.toCharPtr(arena); - return CredentialsHandle(realmLib.realm_app_credentials_new_facebook(accessTokenPtr)); + return CredentialsHandle( + realmLib.realm_app_credentials_new_facebook(accessTokenPtr)); }); } factory CredentialsHandle.googleIdToken(String idToken) { return using((arena) { final idTokenPtr = idToken.toCharPtr(arena); - return CredentialsHandle(realmLib.realm_app_credentials_new_google_id_token(idTokenPtr)); + return CredentialsHandle( + realmLib.realm_app_credentials_new_google_id_token(idTokenPtr)); }); } factory CredentialsHandle.googleAuthCode(String authCode) { return using((arena) { final authCodePtr = authCode.toCharPtr(arena); - return CredentialsHandle(realmLib.realm_app_credentials_new_google_auth_code(authCodePtr)); + return CredentialsHandle( + realmLib.realm_app_credentials_new_google_auth_code(authCodePtr)); }); } factory CredentialsHandle.function(String payload) { return using((arena) { final payloadPtr = payload.toCharPtr(arena); - final credentialsPtr = invokeGetPointer(() => realmLib.realm_app_credentials_new_function(payloadPtr)); + final credentialsPtr = + realmLib.realm_app_credentials_new_function(payloadPtr).raiseIfNull(); return CredentialsHandle(credentialsPtr); }); } @@ -73,7 +82,8 @@ class CredentialsHandle extends HandleBase { factory CredentialsHandle.apiKey(String key) { return using((arena) { final keyPtr = key.toCharPtr(arena); - return CredentialsHandle(realmLib.realm_app_credentials_new_api_key(keyPtr)); + return CredentialsHandle( + realmLib.realm_app_credentials_new_api_key(keyPtr)); }); } diff --git a/packages/realm_dart/lib/src/native/error_handling.dart b/packages/realm_dart/lib/src/native/error_handling.dart index 320ff8b4d..10bda93a7 100644 --- a/packages/realm_dart/lib/src/native/error_handling.dart +++ b/packages/realm_dart/lib/src/native/error_handling.dart @@ -5,24 +5,21 @@ import 'dart:ffi'; import 'package:ffi/ffi.dart'; -import '../realm_object.dart'; +import '../realm_object.dart'; // TODO: Remove this import import 'realm_bindings.dart'; import 'realm_core.dart'; import 'realm_library.dart'; -void invokeGetBool(bool Function() callback, [String? errorMessage]) { - bool success = callback(); - if (!success) { - throwLastError(errorMessage); - } +extension PointerEx on Pointer { + Pointer raiseIfNull([String? message]) => this == nullptr ? throwLastError(message) : this; } -Pointer invokeGetPointer(Pointer Function() callback, [String? errorMessage]) { - final result = callback(); - if (result == nullptr) { - throwLastError(errorMessage); +extension BoolEx on bool { + void raiseIfFalse([String? message]) { + if (!this) { + throwLastError(message); + } } - return result; } class LastError { diff --git a/packages/realm_dart/lib/src/native/list_handle.dart b/packages/realm_dart/lib/src/native/list_handle.dart index 26ed292c2..24bdc7db3 100644 --- a/packages/realm_dart/lib/src/native/list_handle.dart +++ b/packages/realm_dart/lib/src/native/list_handle.dart @@ -22,28 +22,28 @@ class ListHandle extends CollectionHandleBase { bool get isValid => realmLib.realm_list_is_valid(pointer); ResultsHandle asResults() { - final ptr = invokeGetPointer(() => realmLib.realm_list_to_results(pointer)); + final ptr = realmLib.realm_list_to_results(pointer).raiseIfNull(); return ResultsHandle(ptr, root); } int get size { return using((Arena arena) { final size = arena(); - invokeGetBool(() => realmLib.realm_list_size(pointer, size)); + realmLib.realm_list_size(pointer, size).raiseIfFalse(); return size.value; }); } void removeAt(int index) { - invokeGetBool(() => realmLib.realm_list_erase(pointer, index)); + realmLib.realm_list_erase(pointer, index).raiseIfFalse(); } void move(int from, int to) { - invokeGetBool(() => realmLib.realm_list_move(pointer, from, to)); + realmLib.realm_list_move(pointer, from, to).raiseIfFalse(); } void deleteAll() { - invokeGetBool(() => realmLib.realm_list_remove_all(pointer)); + realmLib.realm_list_remove_all(pointer).raiseIfFalse(); } int indexOf(Object? value) { @@ -53,35 +53,39 @@ class ListHandle extends CollectionHandleBase { // TODO: how should this behave for collections final realmValue = value.toNative(arena); - invokeGetBool( - () => realmLib.realm_list_find( - pointer, - realmValue, - outIndex, - outFound, - ), - ); + realmLib + .realm_list_find( + pointer, + realmValue, + outIndex, + outFound, + ) + .raiseIfFalse(); return outFound.value ? outIndex.value : -1; }); } void clear() { - invokeGetBool(() => realmLib.realm_list_clear(pointer)); + realmLib.realm_list_clear(pointer).raiseIfFalse(); } // TODO: avoid taking the [realm] parameter Object? elementAt(Realm realm, int index) { return using((Arena arena) { final realmValue = arena(); - invokeGetBool(() => realmLib.realm_list_get(pointer, index, realmValue)); - return realmValue.toDartValue(realm, () => realmLib.realm_list_get_list(pointer, index), () => realmLib.realm_list_get_dictionary(pointer, index)); + realmLib.realm_list_get(pointer, index, realmValue).raiseIfFalse(); + return realmValue.toDartValue( + realm, + () => realmLib.realm_list_get_list(pointer, index), + () => realmLib.realm_list_get_dictionary(pointer, index), + ); }); } ListHandle? resolveIn(RealmHandle frozenRealm) { return using((Arena arena) { final resultPtr = arena>(); - invokeGetBool(() => realmLib.realm_list_resolve_in(pointer, frozenRealm.pointer, resultPtr)); + realmLib.realm_list_resolve_in(pointer, frozenRealm.pointer, resultPtr).raiseIfFalse(); return resultPtr == nullptr ? null : ListHandle(resultPtr.value, root); }); } @@ -90,7 +94,7 @@ class ListHandle extends CollectionHandleBase { void addOrUpdateAt(int index, Object? value, bool insert) { using((Arena arena) { final realmValue = value.toNative(arena); - invokeGetBool(() => (insert ? realmLib.realm_list_insert : realmLib.realm_list_set)(pointer, index, realmValue.ref)); + (insert ? realmLib.realm_list_insert : realmLib.realm_list_set)(pointer, index, realmValue.ref).raiseIfFalse(); }); } @@ -101,12 +105,12 @@ class ListHandle extends CollectionHandleBase { } ObjectHandle setEmbeddedAt(int index) { - final ptr = invokeGetPointer(() => realmLib.realm_list_set_embedded(pointer, index)); + final ptr = realmLib.realm_list_set_embedded(pointer, index).raiseIfNull(); return ObjectHandle(ptr, root); } ObjectHandle insertEmbeddedAt(int index) { - final ptr = invokeGetPointer(() => realmLib.realm_list_insert_embedded(pointer, index)); + final ptr = realmLib.realm_list_insert_embedded(pointer, index).raiseIfNull(); return ObjectHandle(ptr, root); } @@ -118,27 +122,29 @@ class ListHandle extends CollectionHandleBase { intoRealmQueryArg(args[i], argsPointer + i, arena); } final queryHandle = QueryHandle( - invokeGetPointer( - () => realmLib.realm_query_parse_for_list( - pointer, - query.toCharPtr(arena), - length, - argsPointer, - ), - ), + realmLib + .realm_query_parse_for_list( + pointer, + query.toCharPtr(arena), + length, + argsPointer, + ) + .raiseIfNull(), root); return queryHandle.findAll(); }); } NotificationTokenHandle subscribeForNotifications(NotificationsController controller) { - final ptr = invokeGetPointer(() => realmLib.realm_list_add_notification_callback( + final ptr = realmLib + .realm_list_add_notification_callback( pointer, controller.toPersistentHandle(), realmLib.addresses.realm_dart_delete_persistent_handle, nullptr, Pointer.fromFunction(collectionChangeCallback), - )); + ) + .raiseIfNull(); return NotificationTokenHandle(ptr, root); } } diff --git a/packages/realm_dart/lib/src/native/map_handle.dart b/packages/realm_dart/lib/src/native/map_handle.dart index 4a3eeebea..e7e3f4dda 100644 --- a/packages/realm_dart/lib/src/native/map_handle.dart +++ b/packages/realm_dart/lib/src/native/map_handle.dart @@ -23,7 +23,7 @@ class MapHandle extends CollectionHandleBase { int get size { return using((Arena arena) { final outSize = arena(); - invokeGetBool(() => realmLib.realm_dictionary_size(pointer, outSize)); + realmLib.realm_dictionary_size(pointer, outSize).raiseIfFalse(); return outSize.value; }); } @@ -32,7 +32,7 @@ class MapHandle extends CollectionHandleBase { return using((Arena arena) { final keyNative = key.toNative(arena); final outErased = arena(); - invokeGetBool(() => realmLib.realm_dictionary_erase(pointer, keyNative.ref, outErased)); + realmLib.realm_dictionary_erase(pointer, keyNative.ref, outErased).raiseIfFalse(); return outErased.value; }); } @@ -43,7 +43,7 @@ class MapHandle extends CollectionHandleBase { final keyNative = key.toNative(arena); final outValue = arena(); final outFound = arena(); - invokeGetBool(() => realmLib.realm_dictionary_find(pointer, keyNative.ref, outValue, outFound)); + realmLib.realm_dictionary_find(pointer, keyNative.ref, outValue, outFound).raiseIfFalse(); if (outFound.value) { return outValue.toDartValue( realm, @@ -60,20 +60,20 @@ class MapHandle extends CollectionHandleBase { } void clear() { - invokeGetBool(() => realmLib.realm_dictionary_clear(pointer)); + realmLib.realm_dictionary_clear(pointer).raiseIfFalse(); } ResultsHandle get keys { return using((Arena arena) { final outSize = arena(); final outKeys = arena>(); - invokeGetBool(() => realmLib.realm_dictionary_get_keys(pointer, outSize, outKeys)); + realmLib.realm_dictionary_get_keys(pointer, outSize, outKeys).raiseIfFalse(); return ResultsHandle(outKeys.value, root); }); } ResultsHandle get values { - final ptr = invokeGetPointer(() => realmLib.realm_dictionary_to_results(pointer)); + final ptr = realmLib.realm_dictionary_to_results(pointer).raiseIfNull(); return ResultsHandle(ptr, root); } @@ -81,7 +81,7 @@ class MapHandle extends CollectionHandleBase { return using((Arena arena) { final keyNative = key.toNative(arena); final found = arena(); - invokeGetBool(() => realmLib.realm_dictionary_contains_key(pointer, keyNative.ref, found)); + realmLib.realm_dictionary_contains_key(pointer, keyNative.ref, found).raiseIfFalse(); return found.value; }); } @@ -91,7 +91,7 @@ class MapHandle extends CollectionHandleBase { // TODO: how should this behave for collections final valueNative = value.toNative(arena); final index = arena(); - invokeGetBool(() => realmLib.realm_dictionary_contains_value(pointer, valueNative.ref, index)); + realmLib.realm_dictionary_contains_value(pointer, valueNative.ref, index).raiseIfFalse(); return index.value; }); } @@ -101,7 +101,7 @@ class MapHandle extends CollectionHandleBase { ObjectHandle insertEmbedded(String key) { return using((Arena arena) { final keyNative = key.toNative(arena); - final ptr = invokeGetPointer(() => realmLib.realm_dictionary_insert_embedded(pointer, keyNative.ref)); + final ptr = realmLib.realm_dictionary_insert_embedded(pointer, keyNative.ref).raiseIfNull(); return ObjectHandle(ptr, root); }); } @@ -110,15 +110,15 @@ class MapHandle extends CollectionHandleBase { using((Arena arena) { final keyNative = key.toNative(arena); final valueNative = value.toNative(arena); - invokeGetBool( - () => realmLib.realm_dictionary_insert( - pointer, - keyNative.ref, - valueNative.ref, - nullptr, - nullptr, - ), - ); + realmLib + .realm_dictionary_insert( + pointer, + keyNative.ref, + valueNative.ref, + nullptr, + nullptr, + ) + .raiseIfFalse(); }); } @@ -143,14 +143,14 @@ class MapHandle extends CollectionHandleBase { } final queryHandle = QueryHandle( - invokeGetPointer( - () => realmLib.realm_query_parse_for_results( - values.pointer, - query.toCharPtr(arena), - length, - argsPointer, - ), - ), + realmLib + .realm_query_parse_for_results( + values.pointer, + query.toCharPtr(arena), + length, + argsPointer, + ) + .raiseIfNull(), root); return queryHandle.findAll(); }); @@ -159,19 +159,21 @@ class MapHandle extends CollectionHandleBase { MapHandle? resolveIn(RealmHandle frozenRealm) { return using((Arena arena) { final resultPtr = arena>(); - invokeGetBool(() => realmLib.realm_dictionary_resolve_in(pointer, frozenRealm.pointer, resultPtr)); + realmLib.realm_dictionary_resolve_in(pointer, frozenRealm.pointer, resultPtr).raiseIfFalse(); return resultPtr == nullptr ? null : MapHandle(resultPtr.value, root); }); } NotificationTokenHandle subscribeForNotifications(NotificationsController controller) { - final ptr = invokeGetPointer(() => realmLib.realm_dictionary_add_notification_callback( + final ptr = realmLib + .realm_dictionary_add_notification_callback( pointer, controller.toPersistentHandle(), realmLib.addresses.realm_dart_delete_persistent_handle, nullptr, Pointer.fromFunction(_mapChangeCallback), - )); + ) + .raiseIfNull(); return NotificationTokenHandle(ptr, root); } } diff --git a/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart b/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart index e6e783896..0965966e6 100644 --- a/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart +++ b/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart @@ -20,7 +20,7 @@ class MutableSubscriptionSetHandle extends SubscriptionSetHandle { Pointer get _mutablePointer => super.pointer.cast(); - SubscriptionSetHandle commit() => SubscriptionSetHandle(invokeGetPointer(() => realmLib.realm_sync_subscription_set_commit(_mutablePointer)), root); + SubscriptionSetHandle commit() => SubscriptionSetHandle(realmLib.realm_sync_subscription_set_commit(_mutablePointer).raiseIfNull(), root); SubscriptionHandle insertOrAssignSubscription(ResultsHandle results, String? name, bool update) { if (!update) { @@ -31,15 +31,15 @@ class MutableSubscriptionSetHandle extends SubscriptionSetHandle { return using((arena) { final outIndex = arena(); final outInserted = arena(); - invokeGetBool( - () => realmLib.realm_sync_subscription_set_insert_or_assign_results( - _mutablePointer, - results.pointer, - name?.toCharPtr(arena) ?? nullptr, - outIndex, - outInserted, - ), - ); + realmLib + .realm_sync_subscription_set_insert_or_assign_results( + _mutablePointer, + results.pointer, + name?.toCharPtr(arena) ?? nullptr, + outIndex, + outInserted, + ) + .raiseIfFalse(); return this[outIndex.value]; }); } @@ -47,13 +47,13 @@ class MutableSubscriptionSetHandle extends SubscriptionSetHandle { bool erase(SubscriptionHandle subscription) { return using((arena) { final outErased = arena(); - invokeGetBool( - () => realmLib.realm_sync_subscription_set_erase_by_id( - _mutablePointer, - subscription.id.toNative(arena), - outErased, - ), - ); + realmLib + .realm_sync_subscription_set_erase_by_id( + _mutablePointer, + subscription.id.toNative(arena), + outErased, + ) + .raiseIfFalse(); return outErased.value; }); } @@ -61,13 +61,13 @@ class MutableSubscriptionSetHandle extends SubscriptionSetHandle { bool eraseByName(String name) { return using((arena) { final outErased = arena(); - invokeGetBool( - () => realmLib.realm_sync_subscription_set_erase_by_name( - _mutablePointer, - name.toCharPtr(arena), - outErased, - ), - ); + realmLib + .realm_sync_subscription_set_erase_by_name( + _mutablePointer, + name.toCharPtr(arena), + outErased, + ) + .raiseIfFalse(); return outErased.value; }); } @@ -75,16 +75,16 @@ class MutableSubscriptionSetHandle extends SubscriptionSetHandle { bool eraseByResults(ResultsHandle results) { return using((arena) { final outErased = arena(); - invokeGetBool( - () => realmLib.realm_sync_subscription_set_erase_by_results( - _mutablePointer, - results.pointer, - outErased, - ), - ); + realmLib + .realm_sync_subscription_set_erase_by_results( + _mutablePointer, + results.pointer, + outErased, + ) + .raiseIfFalse(); return outErased.value; }); } - void clear() => invokeGetBool(() => realmLib.realm_sync_subscription_set_clear(_mutablePointer)); + void clear() => realmLib.realm_sync_subscription_set_clear(_mutablePointer).raiseIfFalse(); } diff --git a/packages/realm_dart/lib/src/native/object_handle.dart b/packages/realm_dart/lib/src/native/object_handle.dart index 8c2170653..98cb16fc3 100644 --- a/packages/realm_dart/lib/src/native/object_handle.dart +++ b/packages/realm_dart/lib/src/native/object_handle.dart @@ -22,7 +22,7 @@ class ObjectHandle extends RootedHandleBase { ObjectHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 112); ObjectHandle createEmbedded(int propertyKey) { - final objectPtr = invokeGetPointer(() => realmLib.realm_set_embedded(pointer, propertyKey)); + final objectPtr = realmLib.realm_set_embedded(pointer, propertyKey).raiseIfNull(); return ObjectHandle(objectPtr, root); } @@ -30,7 +30,7 @@ class ObjectHandle extends RootedHandleBase { return using((Arena arena) { final parentPtr = arena>(); final classKeyPtr = arena(); - invokeGetBool(() => realmLib.realm_object_get_parent(pointer, parentPtr, classKeyPtr)); + realmLib.realm_object_get_parent(pointer, parentPtr, classKeyPtr).raiseIfFalse(); final handle = ObjectHandle(parentPtr.value, root); @@ -46,7 +46,7 @@ class ObjectHandle extends RootedHandleBase { Object? getValue(Realm realm, int propertyKey) { return using((Arena arena) { final realmValue = arena(); - invokeGetBool(() => realmLib.realm_get_value(pointer, propertyKey, realmValue)); + realmLib.realm_get_value(pointer, propertyKey, realmValue).raiseIfFalse(); return realmValue.toDartValue( realm, () => realmLib.realm_get_list(pointer, propertyKey), @@ -60,34 +60,34 @@ class ObjectHandle extends RootedHandleBase { void setValue(int propertyKey, Object? value, bool isDefault) { using((Arena arena) { final realmValue = value.toNative(arena); - invokeGetBool( - () => realmLib.realm_set_value( - pointer, - propertyKey, - realmValue.ref, - isDefault, - ), - ); + realmLib + .realm_set_value( + pointer, + propertyKey, + realmValue.ref, + isDefault, + ) + .raiseIfFalse(); }); } ListHandle getList(int propertyKey) { - final ptr = invokeGetPointer(() => realmLib.realm_get_list(pointer, propertyKey)); + final ptr = realmLib.realm_get_list(pointer, propertyKey).raiseIfNull(); return ListHandle(ptr, root); } SetHandle getSet(int propertyKey) { - final ptr = invokeGetPointer(() => realmLib.realm_get_set(pointer, propertyKey)); + final ptr = realmLib.realm_get_set(pointer, propertyKey).raiseIfNull(); return SetHandle(ptr, root); } MapHandle getMap(int propertyKey) { - final ptr = invokeGetPointer(() => realmLib.realm_get_dictionary(pointer, propertyKey)); + final ptr = realmLib.realm_get_dictionary(pointer, propertyKey).raiseIfNull(); return MapHandle(ptr, root); } ResultsHandle getBacklinks(int sourceTableKey, int propertyKey) { - final ptr = invokeGetPointer(() => realmLib.realm_get_backlinks(pointer, sourceTableKey, propertyKey)); + final ptr = realmLib.realm_get_backlinks(pointer, sourceTableKey, propertyKey).raiseIfNull(); return ResultsHandle(ptr, root); } @@ -105,13 +105,13 @@ class ObjectHandle extends RootedHandleBase { } void delete() { - invokeGetBool(() => realmLib.realm_object_delete(pointer)); + realmLib.realm_object_delete(pointer).raiseIfFalse(); } ObjectHandle? resolveIn(RealmHandle frozenRealm) { return using((Arena arena) { final resultPtr = arena>(); - invokeGetBool(() => realmLib.realm_object_resolve_in(pointer, frozenRealm.pointer, resultPtr)); + realmLib.realm_object_resolve_in(pointer, frozenRealm.pointer, resultPtr).raiseIfFalse(); return resultPtr == nullptr ? null : ObjectHandle(resultPtr.value, frozenRealm); }); } @@ -119,13 +119,15 @@ class ObjectHandle extends RootedHandleBase { NotificationTokenHandle subscribeForNotifications(NotificationsController controller, [List? keyPaths]) { return using((Arena arena) { final kpNative = buildAndVerifyKeyPath(keyPaths); - final ptr = invokeGetPointer(() => realmLib.realm_object_add_notification_callback( + final ptr = realmLib + .realm_object_add_notification_callback( pointer, controller.toPersistentHandle(), realmLib.addresses.realm_dart_delete_persistent_handle, kpNative, Pointer.fromFunction(_objectChangeCallback), - )); + ) + .raiseIfNull(); return NotificationTokenHandle(ptr, root); }); @@ -145,7 +147,7 @@ class ObjectHandle extends RootedHandleBase { } // TODO(kn): // call to classKey getter involves a native call, which is not ideal - return invokeGetPointer(() => realmLib.realm_create_key_path_array(root.pointer, classKey, length, keypathsNative)); + return realmLib.realm_create_key_path_array(root.pointer, classKey, length, keypathsNative).raiseIfNull(); }); } } diff --git a/packages/realm_dart/lib/src/native/query_handle.dart b/packages/realm_dart/lib/src/native/query_handle.dart index 29016844a..19fe6f59d 100644 --- a/packages/realm_dart/lib/src/native/query_handle.dart +++ b/packages/realm_dart/lib/src/native/query_handle.dart @@ -15,7 +15,7 @@ class QueryHandle extends RootedHandleBase { ResultsHandle findAll() { try { - final resultsPointer = invokeGetPointer(() => realmLib.realm_query_find_all(pointer)); + final resultsPointer = realmLib.realm_query_find_all(pointer).raiseIfNull(); return ResultsHandle(resultsPointer, root); } finally { release(); diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index d28c989a7..2710f8c2f 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -194,7 +194,7 @@ void createCollection(Realm realm, RealmValue value, Pointer Functio try { switch (value.collectionType) { case RealmCollectionType.list: - final listPointer = invokeGetPointer(createList); + final listPointer = createList().raiseIfNull(); final listHandle = ListHandle(listPointer, realm.handle); collectionHandle = listHandle; @@ -207,7 +207,7 @@ void createCollection(Realm realm, RealmValue value, Pointer Functio list.add(item); } case RealmCollectionType.map: - final mapPointer = invokeGetPointer(createMap); + final mapPointer = createMap().raiseIfNull(); final mapHandle = MapHandle(mapPointer, realm.handle); collectionHandle = mapHandle; @@ -296,7 +296,7 @@ class _RealmCore { AsyncOpenTaskHandle createRealmAsyncOpenTask(FlexibleSyncConfiguration config) { final configHandle = ConfigHandle.from(config); - final asyncOpenTaskPtr = invokeGetPointer(() => realmLib.realm_open_synchronized(configHandle.pointer), "Error opening realm at path ${config.path}"); + final asyncOpenTaskPtr = realmLib.realm_open_synchronized(configHandle.pointer).raiseIfNull("Error opening realm at path ${config.path}"); return AsyncOpenTaskHandle(asyncOpenTaskPtr); } @@ -329,7 +329,7 @@ class _RealmCore { return; } - final realmPtr = invokeGetPointer(() => realmLib.realm_from_thread_safe_reference(realmSafePtr, scheduler.handle.pointer)); + final realmPtr = realmLib.realm_from_thread_safe_reference(realmSafePtr, scheduler.handle.pointer).raiseIfNull(); completer.complete(RealmHandle(realmPtr)); }); } @@ -342,12 +342,12 @@ class _RealmCore { AsyncOpenTaskHandle handle, RealmAsyncOpenProgressNotificationsController controller) { final callback = Pointer.fromFunction(syncProgressCallback); final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); - final tokenPtr = invokeGetPointer(() => realmLib.realm_async_open_task_register_download_progress_notifier( + final tokenPtr = realmLib.realm_async_open_task_register_download_progress_notifier( handle.pointer, realmLib.addresses.realm_dart_sync_progress_callback, userdata.cast(), realmLib.addresses.realm_dart_userdata_async_free, - )); + ).raiseIfNull(); return AsyncOpenTaskProgressNotificationTokenHandle(tokenPtr); } @@ -356,7 +356,7 @@ class _RealmCore { void deleteRealmFiles(String path) { using((Arena arena) { final realmDeleted = arena(); - invokeGetBool(() => realmLib.realm_delete_files(path.toCharPtr(arena), realmDeleted), "Error deleting realm at path $path"); + realmLib.realm_delete_files(path.toCharPtr(arena), realmDeleted).raiseIfFalse("Error deleting realm at path $path"); }); } @@ -403,7 +403,7 @@ class _RealmCore { AppHandle? getApp(String id, String? baseUrl) { return using((arena) { final outApp = arena>(); - invokeGetBool(() => realmLib.realm_app_get_cached(id.toCharPtr(arena), baseUrl == null ? nullptr : baseUrl.toCharPtr(arena), outApp)); + realmLib.realm_app_get_cached(id.toCharPtr(arena), baseUrl == null ? nullptr : baseUrl.toCharPtr(arena), outApp).raiseIfFalse(); return outApp.value == nullptr ? null : AppHandle(outApp.value); }); } @@ -473,7 +473,7 @@ class _RealmCore { Future callAppFunction(App app, User user, String functionName, String? argsAsJSON) { return using((arena) { final completer = Completer(); - invokeGetBool(() => realmLib.realm_app_call_function( + realmLib.realm_app_call_function( app.handle.pointer, user.handle.pointer, functionName.toCharPtr(arena), @@ -482,7 +482,7 @@ class _RealmCore { realmLib.addresses.realm_dart_return_string_callback, createAsyncFunctionCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - )); + ).raiseIfFalse(); return completer.future; }); } @@ -731,7 +731,7 @@ extension RealmValueEx on realm_value_t { throw RealmException('toDartValue called with a list argument but without a list getter'); } - final listPointer = invokeGetPointer(() => getList()); + final listPointer = getList().raiseIfNull(); final listHandle = ListHandle(listPointer, realm.handle); return realm.createList(listHandle, null); case realm_value_type.RLM_TYPE_DICTIONARY: @@ -739,7 +739,7 @@ extension RealmValueEx on realm_value_t { throw RealmException('toDartValue called with a list argument but without a list getter'); } - final mapPointer = invokeGetPointer(() => getMap()); + final mapPointer = getMap().raiseIfNull(); final mapHandle = MapHandle(mapPointer, realm.handle); return realm.createMap(mapHandle, null); default: diff --git a/packages/realm_dart/lib/src/native/realm_handle.dart b/packages/realm_dart/lib/src/native/realm_handle.dart index 2636c894e..de236ba79 100644 --- a/packages/realm_dart/lib/src/native/realm_handle.dart +++ b/packages/realm_dart/lib/src/native/realm_handle.dart @@ -37,7 +37,7 @@ class RealmHandle extends HandleBase { factory RealmHandle.open(Configuration config) { final configHandle = ConfigHandle.from(config); - final realmPtr = invokeGetPointer(() => realmLib.realm_open(configHandle.pointer), 'Error opening realm at path ${config.path}'); + final realmPtr = realmLib.realm_open(configHandle.pointer).raiseIfNull('Error opening realm at path ${config.path}'); return RealmHandle(realmPtr); } @@ -68,13 +68,13 @@ class RealmHandle extends HandleBase { ObjectHandle createWithPrimaryKey(int classKey, Object? primaryKey) { return using((Arena arena) { final realmValue = primaryKey.toNative(arena); - final realmPtr = invokeGetPointer(() => realmLib.realm_object_create_with_primary_key(pointer, classKey, realmValue.ref)); + final realmPtr = realmLib.realm_object_create_with_primary_key(pointer, classKey, realmValue.ref).raiseIfNull(); return ObjectHandle(realmPtr, this); }); } ObjectHandle create(int classKey) { - final realmPtr = invokeGetPointer(() => realmLib.realm_object_create(pointer, classKey)); + final realmPtr = realmLib.realm_object_create(pointer, classKey).raiseIfNull(); return ObjectHandle(realmPtr, this); } @@ -82,12 +82,14 @@ class RealmHandle extends HandleBase { return using((Arena arena) { final realmValue = primaryKey.toNative(arena); final didCreate = arena(); - final realmPtr = invokeGetPointer(() => realmLib.realm_object_get_or_create_with_primary_key( + final realmPtr = realmLib + .realm_object_get_or_create_with_primary_key( pointer, classKey, realmValue.ref, didCreate, - )); + ) + .raiseIfNull(); return ObjectHandle(realmPtr, this); }); } @@ -95,14 +97,14 @@ class RealmHandle extends HandleBase { bool compact() { return using((arena) { final outDidCompact = arena(); - invokeGetBool(() => realmLib.realm_compact(pointer, outDidCompact)); + realmLib.realm_compact(pointer, outDidCompact).raiseIfFalse(); return outDidCompact.value; }); } void writeCopy(Configuration config) { final configHandle = ConfigHandle.from(config); - invokeGetBool(() => realmLib.realm_convert_with_config(pointer, configHandle.pointer, false)); + realmLib.realm_convert_with_config(pointer, configHandle.pointer, false).raiseIfFalse(); } ResultsHandle queryClass(int classKey, String query, List args) { @@ -113,24 +115,24 @@ class RealmHandle extends HandleBase { intoRealmQueryArg(args[i], argsPointer + i, arena); } final queryHandle = QueryHandle( - invokeGetPointer( - () => realmLib.realm_query_parse( - pointer, - classKey, - query.toCharPtr(arena), - length, - argsPointer, - ), - ), + realmLib + .realm_query_parse( + pointer, + classKey, + query.toCharPtr(arena), + length, + argsPointer, + ) + .raiseIfNull(), this); return queryHandle.findAll(); }); } - RealmHandle freeze() => RealmHandle(invokeGetPointer(() => realmLib.realm_freeze(pointer))); + RealmHandle freeze() => RealmHandle(realmLib.realm_freeze(pointer).raiseIfNull()); SessionHandle getSession() { - return SessionHandle(invokeGetPointer(() => realmLib.realm_sync_session_get(pointer)), this); + return SessionHandle(realmLib.realm_sync_session_get(pointer).raiseIfNull(), this); } bool get isFrozen { @@ -138,7 +140,7 @@ class RealmHandle extends HandleBase { } SubscriptionSetHandle get subscriptions { - return SubscriptionSetHandle(invokeGetPointer(() => realmLib.realm_sync_get_active_subscription_set(pointer)), this); + return SubscriptionSetHandle(realmLib.realm_sync_get_active_subscription_set(pointer).raiseIfNull(), this); } void disableAutoRefreshForTesting() { @@ -146,7 +148,7 @@ class RealmHandle extends HandleBase { } void close() { - invokeGetBool(() => realmLib.realm_close(pointer), "Realm close failed"); + realmLib.realm_close(pointer).raiseIfFalse("Realm close failed"); } bool get isClosed { @@ -154,11 +156,11 @@ class RealmHandle extends HandleBase { } void beginWrite() { - invokeGetBool(() => realmLib.realm_begin_write(pointer), "Could not begin write"); + realmLib.realm_begin_write(pointer).raiseIfFalse("Could not begin write"); } void commitWrite() { - invokeGetBool(() => realmLib.realm_commit(pointer), "Could not commit write"); + realmLib.realm_commit(pointer).raiseIfFalse("Could not commit write"); } Future beginWriteAsync(CancellationToken? ct) { @@ -171,14 +173,16 @@ class RealmHandle extends HandleBase { if (ct?.isCancelled != true) { using((arena) { final transactionId = arena(); - invokeGetBool(() => realmLib.realm_async_begin_write( + realmLib + .realm_async_begin_write( pointer, Pointer.fromFunction(_completeAsyncBeginWrite), completer.toPersistentHandle(), realmLib.addresses.realm_dart_delete_persistent_handle, true, transactionId, - )); + ) + .raiseIfFalse(); id = transactionId.value; }); } @@ -195,14 +199,16 @@ class RealmHandle extends HandleBase { if (ct?.isCancelled != true) { using((arena) { final transactionId = arena(); - invokeGetBool(() => realmLib.realm_async_commit( + realmLib + .realm_async_commit( pointer, Pointer.fromFunction(_completeAsyncCommit), completer.toPersistentHandle(), realmLib.addresses.realm_dart_delete_persistent_handle, false, transactionId, - )); + ) + .raiseIfFalse(); id = transactionId.value; }); } @@ -212,7 +218,7 @@ class RealmHandle extends HandleBase { bool _cancelAsync(int cancellationId) { return using((Arena arena) { final didCancel = arena(); - invokeGetBool(() => realmLib.realm_async_cancel(pointer, cancellationId, didCancel)); + realmLib.realm_async_cancel(pointer, cancellationId, didCancel).raiseIfFalse(); return didCancel.value; }); } @@ -236,13 +242,13 @@ class RealmHandle extends HandleBase { } void rollbackWrite() { - invokeGetBool(() => realmLib.realm_rollback(pointer), "Could not rollback write"); + realmLib.realm_rollback(pointer).raiseIfFalse("Could not rollback write"); } bool refresh() { return using((Arena arena) { final didRefresh = arena(); - invokeGetBool(() => realmLib.realm_refresh(pointer, didRefresh), "Could not refresh"); + realmLib.realm_refresh(pointer, didRefresh).raiseIfFalse("Could not refresh"); return didRefresh.value; }); } @@ -271,56 +277,64 @@ class RealmHandle extends HandleBase { } ResultsHandle findAll(int classKey) { - final ptr = invokeGetPointer(() => realmLib.realm_object_find_all(pointer, classKey)); + final ptr = realmLib.realm_object_find_all(pointer, classKey).raiseIfNull(); return ResultsHandle(ptr, this); } ObjectHandle? find(int classKey, Object? primaryKey) { return using((Arena arena) { final realmValue = primaryKey.toNative(arena); - final ptr = realmLib.realm_object_find_with_primary_key(pointer, classKey, realmValue.ref, nullptr); - if (ptr == nullptr) { + final found = arena(); + final ptr = realmLib.realm_object_find_with_primary_key(pointer, classKey, realmValue.ref, found); + if (!found.value) { return null; } - return ObjectHandle(ptr, this); + return ObjectHandle(ptr.raiseIfNull(), this); }); } ObjectHandle? findExisting(int classKey, ObjectHandle other) { final key = realmLib.realm_object_get_key(other.pointer); - final ptr = invokeGetPointer(() => realmLib.realm_get_object(pointer, classKey, key)); - return ptr.convert((p) => ObjectHandle(p, this)); + final ptr = realmLib.realm_get_object(pointer, classKey, key).raiseIfNull(); + return ObjectHandle(ptr, this); } void renameProperty(String objectType, String oldName, String newName, SchemaHandle schema) { using((Arena arena) { - invokeGetBool(() => - realmLib.realm_schema_rename_property(pointer, schema.pointer, objectType.toCharPtr(arena), oldName.toCharPtr(arena), newName.toCharPtr(arena))); + realmLib + .realm_schema_rename_property( + pointer, + schema.pointer, + objectType.toCharPtr(arena), + oldName.toCharPtr(arena), + newName.toCharPtr(arena), + ) + .raiseIfFalse(); }); } bool deleteType(String objectType) { return using((Arena arena) { final tableDeleted = arena(); - invokeGetBool(() => realmLib.realm_remove_table(pointer, objectType.toCharPtr(arena), tableDeleted)); + realmLib.realm_remove_table(pointer, objectType.toCharPtr(arena), tableDeleted).raiseIfFalse(); return tableDeleted.value; }); } ObjectHandle getObject(int classKey, int objectKey) { - final ptr = invokeGetPointer(() => realmLib.realm_get_object(pointer, classKey, objectKey)); + final ptr = realmLib.realm_get_object(pointer, classKey, objectKey).raiseIfNull(); return ObjectHandle(ptr, this); } CallbackTokenHandle subscribeForSchemaNotifications(Realm realm) { - final ptr = invokeGetPointer( - () => realmLib.realm_add_schema_changed_callback( - pointer, - Pointer.fromFunction(_schemaChangeCallback), - realm.toPersistentHandle(), - realmLib.addresses.realm_dart_delete_persistent_handle, - ), - ); + final ptr = realmLib + .realm_add_schema_changed_callback( + pointer, + Pointer.fromFunction(_schemaChangeCallback), + realm.toPersistentHandle(), + realmLib.addresses.realm_dart_delete_persistent_handle, + ) + .raiseIfNull(); return CallbackTokenHandle(ptr, this); } @@ -333,7 +347,7 @@ class RealmHandle extends HandleBase { RealmSchema _readSchema(Arena arena, {int expectedSize = 10}) { final classesPtr = arena(expectedSize); final actualCount = arena(); - invokeGetBool(() => realmLib.realm_get_class_keys(pointer, classesPtr, expectedSize, actualCount)); + realmLib.realm_get_class_keys(pointer, classesPtr, expectedSize, actualCount).raiseIfFalse(); if (expectedSize < actualCount.value) { arena.free(classesPtr); return _readSchema(arena, expectedSize: actualCount.value); @@ -343,7 +357,7 @@ class RealmHandle extends HandleBase { for (var i = 0; i < actualCount.value; i++) { final classInfo = arena(); final classKey = (classesPtr + i).value; - invokeGetBool(() => realmLib.realm_get_class(pointer, classKey, classInfo)); + realmLib.realm_get_class(pointer, classKey, classInfo).raiseIfFalse(); final name = classInfo.ref.name.cast().toDartString(); final baseType = ObjectType.values.firstWhere((element) => element.flags == classInfo.ref.flags, @@ -358,7 +372,7 @@ class RealmHandle extends HandleBase { SchemaObject _getSchemaForClassKey(int classKey, String name, ObjectType baseType, Arena arena, {int expectedSize = 10}) { final actualCount = arena(); final propertiesPtr = arena(expectedSize); - invokeGetBool(() => realmLib.realm_get_class_properties(pointer, classKey, propertiesPtr, expectedSize, actualCount)); + realmLib.realm_get_class_properties(pointer, classKey, propertiesPtr, expectedSize, actualCount).raiseIfFalse(); if (expectedSize < actualCount.value) { // The supplied array was too small - resize it @@ -400,8 +414,8 @@ class RealmHandle extends HandleBase { return using((Arena arena) { final found = arena(); final classInfo = arena(); - invokeGetBool(() => realmLib.realm_find_class(pointer, schema.name.toCharPtr(arena), found, classInfo)); - // "Error getting class ${schema.name} from realm at ${realm.config.path}"); + realmLib.realm_find_class(pointer, schema.name.toCharPtr(arena), found, classInfo).raiseIfFalse(); + // "Error getting class ${schema.name} from realm at ${realm.config.path}"); if (!found.value) { throwLastError(); //"Class ${schema.name} not found in ${realm.config.path}"); @@ -414,12 +428,11 @@ class RealmHandle extends HandleBase { Map _getPropertiesMetadata(int classKey, String? primaryKeyName, Arena arena) { final propertyCountPtr = arena(); - invokeGetBool(() => realmLib.realm_get_property_keys(pointer, classKey, nullptr, 0, propertyCountPtr), "Error getting property count"); + realmLib.realm_get_property_keys(pointer, classKey, nullptr, 0, propertyCountPtr).raiseIfFalse("Error getting property count"); var propertyCount = propertyCountPtr.value; final propertiesPtr = arena(propertyCount); - invokeGetBool( - () => realmLib.realm_get_class_properties(pointer, classKey, propertiesPtr, propertyCount, propertyCountPtr), "Error getting class properties."); + realmLib.realm_get_class_properties(pointer, classKey, propertiesPtr, propertyCount, propertyCountPtr).raiseIfFalse("Error getting class properties."); propertyCount = propertyCountPtr.value; Map result = {}; diff --git a/packages/realm_dart/lib/src/native/results_handle.dart b/packages/realm_dart/lib/src/native/results_handle.dart index a08406ddb..c21c7c2a3 100644 --- a/packages/realm_dart/lib/src/native/results_handle.dart +++ b/packages/realm_dart/lib/src/native/results_handle.dart @@ -26,14 +26,14 @@ class ResultsHandle extends RootedHandleBase { intoRealmQueryArg(args[i], argsPointer + i, arena); } final queryHandle = QueryHandle( - invokeGetPointer( - () => realmLib.realm_query_parse_for_results( - pointer, - query.toCharPtr(arena), - length, - argsPointer, - ), - ), + realmLib + .realm_query_parse_for_results( + pointer, + query.toCharPtr(arena), + length, + argsPointer, + ) + .raiseIfNull(), root); return queryHandle.findAll(); }); @@ -46,27 +46,27 @@ class ResultsHandle extends RootedHandleBase { // TODO: how should this behave for collections final realmValue = value.toNative(arena); - invokeGetBool( - () => realmLib.realm_results_find( - pointer, - realmValue, - outIndex, - outFound, - ), - ); + realmLib + .realm_results_find( + pointer, + realmValue, + outIndex, + outFound, + ) + .raiseIfFalse(); return outFound.value ? outIndex.value : -1; }); } ObjectHandle getObjectAt(int index) { - final objectPointer = invokeGetPointer(() => realmLib.realm_results_get_object(pointer, index)); + final objectPointer = realmLib.realm_results_get_object(pointer, index).raiseIfNull(); return ObjectHandle(objectPointer, root); } int get count { return using((Arena arena) { final countPtr = arena(); - invokeGetBool(() => realmLib.realm_results_count(pointer, countPtr)); + realmLib.realm_results_count(pointer, countPtr).raiseIfFalse(); return countPtr.value; }); } @@ -74,29 +74,29 @@ class ResultsHandle extends RootedHandleBase { bool isValid() { return using((arena) { final isValid = arena(); - invokeGetBool(() => realmLib.realm_results_is_valid(pointer, isValid)); + realmLib.realm_results_is_valid(pointer, isValid).raiseIfFalse(); return isValid.value; }); } void deleteAll() { - invokeGetBool(() => realmLib.realm_results_delete_all(pointer)); + realmLib.realm_results_delete_all(pointer).raiseIfFalse(); } ResultsHandle snapshot() { - final resultsPointer = invokeGetPointer(() => realmLib.realm_results_snapshot(pointer)); + final resultsPointer = realmLib.realm_results_snapshot(pointer).raiseIfNull(); return ResultsHandle(resultsPointer, root); } ResultsHandle resolveIn(RealmHandle realmHandle) { - final ptr = invokeGetPointer(() => realmLib.realm_results_resolve_in(pointer, realmHandle.pointer)); + final ptr = realmLib.realm_results_resolve_in(pointer, realmHandle.pointer).raiseIfNull(); return ResultsHandle(ptr, realmHandle); } Object? elementAt(Realm realm, int index) { return using((Arena arena) { final realmValue = arena(); - invokeGetBool(() => realmLib.realm_results_get(pointer, index, realmValue)); + realmLib.realm_results_get(pointer, index, realmValue).raiseIfFalse(); return realmValue.toDartValue( realm, () => realmLib.realm_results_get_list(pointer, index), @@ -106,15 +106,15 @@ class ResultsHandle extends RootedHandleBase { } NotificationTokenHandle subscribeForNotifications(NotificationsController controller) { - final ptr = invokeGetPointer( - () => realmLib.realm_results_add_notification_callback( - pointer, - controller.toPersistentHandle(), - realmLib.addresses.realm_dart_delete_persistent_handle, - nullptr, - Pointer.fromFunction(collectionChangeCallback), - ), - ); + final ptr = realmLib + .realm_results_add_notification_callback( + pointer, + controller.toPersistentHandle(), + realmLib.addresses.realm_dart_delete_persistent_handle, + nullptr, + Pointer.fromFunction(collectionChangeCallback), + ) + .raiseIfNull(); return NotificationTokenHandle(ptr, root); } } diff --git a/packages/realm_dart/lib/src/native/schema_handle.dart b/packages/realm_dart/lib/src/native/schema_handle.dart index 39efd7228..a92ae7ca8 100644 --- a/packages/realm_dart/lib/src/native/schema_handle.dart +++ b/packages/realm_dart/lib/src/native/schema_handle.dart @@ -77,7 +77,7 @@ class SchemaHandle extends HandleBase { (schemaProperties + i).value = properties; } - final schemaPtr = invokeGetPointer(() => realmLib.realm_schema_new(schemaClasses, classCount, schemaProperties)); + final schemaPtr = realmLib.realm_schema_new(schemaClasses, classCount, schemaProperties).raiseIfNull(); return SchemaHandle(schemaPtr); }); } diff --git a/packages/realm_dart/lib/src/native/session_handle.dart b/packages/realm_dart/lib/src/native/session_handle.dart index df91b229f..30e18966b 100644 --- a/packages/realm_dart/lib/src/native/session_handle.dart +++ b/packages/realm_dart/lib/src/native/session_handle.dart @@ -117,14 +117,14 @@ class SessionHandle extends RootedHandleBase { SyncSessionNotificationTokenHandle subscribeForConnectionStateNotifications(SessionConnectionStateController controller) { final callback = Pointer.fromFunction(_onConnectionStateChange); final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); - final ptr = invokeGetPointer( - () => realmLib.realm_sync_session_register_connection_state_change_callback( - pointer, - realmLib.addresses.realm_dart_sync_connection_state_changed_callback, - userdata.cast(), - realmLib.addresses.realm_dart_userdata_async_free, - ), - ); + final ptr = realmLib + .realm_sync_session_register_connection_state_change_callback( + pointer, + realmLib.addresses.realm_dart_sync_connection_state_changed_callback, + userdata.cast(), + realmLib.addresses.realm_dart_userdata_async_free, + ) + .raiseIfNull(); return SyncSessionNotificationTokenHandle(ptr); } @@ -136,13 +136,10 @@ class SessionHandle extends RootedHandleBase { final isStreaming = mode == ProgressMode.reportIndefinitely; final callback = Pointer.fromFunction(syncProgressCallback); final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); - final tokenPtr = invokeGetPointer(() => realmLib.realm_sync_session_register_progress_notifier( - pointer, - realmLib.addresses.realm_dart_sync_progress_callback, - direction.index, - isStreaming, - userdata.cast(), - realmLib.addresses.realm_dart_userdata_async_free)); + final tokenPtr = realmLib + .realm_sync_session_register_progress_notifier(pointer, realmLib.addresses.realm_dart_sync_progress_callback, direction.index, isStreaming, + userdata.cast(), realmLib.addresses.realm_dart_userdata_async_free) + .raiseIfNull(); return SyncSessionNotificationTokenHandle(tokenPtr); } } diff --git a/packages/realm_dart/lib/src/native/set_handle.dart b/packages/realm_dart/lib/src/native/set_handle.dart index 7ad0e317b..994a48d70 100644 --- a/packages/realm_dart/lib/src/native/set_handle.dart +++ b/packages/realm_dart/lib/src/native/set_handle.dart @@ -19,7 +19,7 @@ class SetHandle extends RootedHandleBase { SetHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 96); ResultsHandle get asResults { - final ptr = invokeGetPointer(() => realmLib.realm_set_to_results(pointer)); + final ptr = realmLib.realm_set_to_results(pointer).raiseIfNull(); return ResultsHandle(ptr, root); } @@ -31,14 +31,14 @@ class SetHandle extends RootedHandleBase { intoRealmQueryArg(args[i], argsPointer + i, arena); } final queryHandle = QueryHandle( - invokeGetPointer( - () => realmLib.realm_query_parse_for_set( - pointer, - query.toCharPtr(arena), - length, - argsPointer, - ), - ), + realmLib + .realm_query_parse_for_set( + pointer, + query.toCharPtr(arena), + length, + argsPointer, + ) + .raiseIfNull(), root); return queryHandle.findAll(); }); @@ -49,7 +49,7 @@ class SetHandle extends RootedHandleBase { final realmValue = value.toNative(arena); final outIndex = arena(); final outInserted = arena(); - invokeGetBool(() => realmLib.realm_set_insert(pointer, realmValue.ref, outIndex, outInserted)); + realmLib.realm_set_insert(pointer, realmValue.ref, outIndex, outInserted).raiseIfFalse(); return outInserted.value; }); } @@ -58,7 +58,7 @@ class SetHandle extends RootedHandleBase { Object? elementAt(Realm realm, int index) { return using((Arena arena) { final realmValue = arena(); - invokeGetBool(() => realmLib.realm_set_get(pointer, index, realmValue)); + realmLib.realm_set_get(pointer, index, realmValue).raiseIfFalse(); final result = realmValue.toDartValue( realm, () => throw RealmException('Sets cannot contain collections'), @@ -74,7 +74,7 @@ class SetHandle extends RootedHandleBase { final realmValue = value.toNative(arena); final outIndex = arena(); final outFound = arena(); - invokeGetBool(() => realmLib.realm_set_find(pointer, realmValue.ref, outIndex, outFound)); + realmLib.realm_set_find(pointer, realmValue.ref, outIndex, outFound).raiseIfFalse(); return outFound.value; }); } @@ -84,19 +84,19 @@ class SetHandle extends RootedHandleBase { // TODO: do we support sets containing mixed collections final realmValue = value.toNative(arena); final outErased = arena(); - invokeGetBool(() => realmLib.realm_set_erase(pointer, realmValue.ref, outErased)); + realmLib.realm_set_erase(pointer, realmValue.ref, outErased).raiseIfFalse(); return outErased.value; }); } void clear() { - invokeGetBool(() => realmLib.realm_set_clear(pointer)); + realmLib.realm_set_clear(pointer).raiseIfFalse(); } int get size { return using((Arena arena) { final outSize = arena(); - invokeGetBool(() => realmLib.realm_set_size(pointer, outSize)); + realmLib.realm_set_size(pointer, outSize).raiseIfFalse(); return outSize.value; }); } @@ -106,25 +106,27 @@ class SetHandle extends RootedHandleBase { } void deleteAll() { - invokeGetBool(() => realmLib.realm_set_remove_all(pointer)); + realmLib.realm_set_remove_all(pointer).raiseIfFalse(); } SetHandle? resolveIn(RealmHandle frozenRealm) { return using((Arena arena) { final resultPtr = arena>(); - invokeGetBool(() => realmLib.realm_set_resolve_in(pointer, frozenRealm.pointer, resultPtr)); + realmLib.realm_set_resolve_in(pointer, frozenRealm.pointer, resultPtr).raiseIfFalse(); return resultPtr == nullptr ? null : SetHandle(resultPtr.value, root); }); } NotificationTokenHandle subscribeForNotifications(NotificationsController controller) { - final ptr = invokeGetPointer(() => realmLib.realm_set_add_notification_callback( + final ptr = realmLib + .realm_set_add_notification_callback( pointer, controller.toPersistentHandle(), realmLib.addresses.realm_dart_delete_persistent_handle, nullptr, Pointer.fromFunction(collectionChangeCallback), - )); + ) + .raiseIfNull(); return NotificationTokenHandle(ptr, root); } } diff --git a/packages/realm_dart/lib/src/native/subscription_set_handle.dart b/packages/realm_dart/lib/src/native/subscription_set_handle.dart index eebebd5f7..3f5f0706d 100644 --- a/packages/realm_dart/lib/src/native/subscription_set_handle.dart +++ b/packages/realm_dart/lib/src/native/subscription_set_handle.dart @@ -25,7 +25,7 @@ class SubscriptionSetHandle extends RootedHandleBase pointer, RealmHandle root) : super(root, pointer, 128); - void refresh() => invokeGetBool(() => realmLib.realm_sync_subscription_set_refresh(pointer)); + void refresh() => realmLib.realm_sync_subscription_set_refresh(pointer).raiseIfFalse(); int get size => realmLib.realm_sync_subscription_set_size(pointer); @@ -35,7 +35,7 @@ class SubscriptionSetHandle extends RootedHandleBase SubscriptionHandle(invokeGetPointer(() => realmLib.realm_sync_subscription_at(pointer, index))); + SubscriptionHandle operator [](int index) => SubscriptionHandle(realmLib.realm_sync_subscription_at(pointer, index).raiseIfNull()); SubscriptionHandle? findByName(String name) { return using((arena) { @@ -59,8 +59,7 @@ class SubscriptionSetHandle extends RootedHandleBase SubscriptionSetState.values[realmLib.realm_sync_subscription_set_state(pointer)]; - MutableSubscriptionSetHandle toMutable() => - MutableSubscriptionSetHandle(invokeGetPointer(() => realmLib.realm_sync_make_subscription_set_mutable(pointer)), root); + MutableSubscriptionSetHandle toMutable() => MutableSubscriptionSetHandle(realmLib.realm_sync_make_subscription_set_mutable(pointer).raiseIfNull(), root); static void _stateChangeCallback(Object userdata, int state) { final completer = userdata as CancellableCompleter; diff --git a/packages/realm_dart/lib/src/native/user_handle.dart b/packages/realm_dart/lib/src/native/user_handle.dart index 42438501b..0573f02ea 100644 --- a/packages/realm_dart/lib/src/native/user_handle.dart +++ b/packages/realm_dart/lib/src/native/user_handle.dart @@ -34,7 +34,7 @@ class UserHandle extends HandleBase { } String get id { - final idPtr = invokeGetPointer(() => realmLib.realm_user_get_identity(pointer), "Error while getting user id"); + final idPtr = realmLib.realm_user_get_identity(pointer).raiseIfNull("Error while getting user id"); final userId = idPtr.cast().toDartString(); return userId; } @@ -48,7 +48,7 @@ class UserHandle extends HandleBase { List _userGetIdentities(Arena arena, {int expectedSize = 2}) { final actualCount = arena(); final identitiesPtr = arena(expectedSize); - invokeGetBool(() => realmLib.realm_user_get_all_identities(pointer, identitiesPtr, expectedSize, actualCount)); + realmLib.realm_user_get_all_identities(pointer, identitiesPtr, expectedSize, actualCount).raiseIfFalse(); if (expectedSize < actualCount.value) { // The supplied array was too small - resize it @@ -68,32 +68,32 @@ class UserHandle extends HandleBase { } Future logOut() async { - invokeGetBool(() => realmLib.realm_user_log_out(pointer), "Logout failed"); + realmLib.realm_user_log_out(pointer).raiseIfFalse("Logout failed"); } String? get deviceId { - final deviceId = invokeGetPointer(() => realmLib.realm_user_get_device_id(pointer)); + final deviceId = realmLib.realm_user_get_device_id(pointer).raiseIfNull(); return deviceId.cast().toRealmDartString(treatEmptyAsNull: true, freeRealmMemory: true); } UserProfile get profileData { - final data = invokeGetPointer(() => realmLib.realm_user_get_profile_data(pointer)); + final data = realmLib.realm_user_get_profile_data(pointer).raiseIfNull(); final dynamic profileData = jsonDecode(data.cast().toRealmDartString(freeRealmMemory: true)!); return UserProfile(profileData as Map); } String get refreshToken { - final token = invokeGetPointer(() => realmLib.realm_user_get_refresh_token(pointer)); + final token = realmLib.realm_user_get_refresh_token(pointer).raiseIfNull(); return token.cast().toRealmDartString(freeRealmMemory: true)!; } String get accessToken { - final token = invokeGetPointer(() => realmLib.realm_user_get_access_token(pointer)); + final token = realmLib.realm_user_get_access_token(pointer).raiseIfNull(); return token.cast().toRealmDartString(freeRealmMemory: true)!; } String get path { - final syncConfigPtr = invokeGetPointer(() => realmLib.realm_flx_sync_config_new(pointer)); + final syncConfigPtr = realmLib.realm_flx_sync_config_new(pointer).raiseIfNull(); try { final path = realmLib.realm_app_sync_client_get_default_file_path_for_realm(syncConfigPtr, nullptr); return path.cast().toRealmDartString(freeRealmMemory: true)!; @@ -109,17 +109,14 @@ class UserHandle extends HandleBase { Future linkCredentials(AppHandle app, CredentialsHandle credentials) { final completer = Completer(); - invokeGetBool( - () => realmLib.realm_app_link_user( + realmLib.realm_app_link_user( app.pointer, pointer, credentials.pointer, realmLib.addresses.realm_dart_user_completion_callback, createAsyncUserCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - ), - "Link credentials failed", - ); + ).raiseIfFalse("Link credentials failed"); return completer.future; } @@ -127,16 +124,14 @@ class UserHandle extends HandleBase { return using((Arena arena) { final namePtr = name.toCharPtr(arena); final completer = Completer(); - invokeGetBool( - () => realmLib.realm_app_user_apikey_provider_client_create_apikey( + realmLib.realm_app_user_apikey_provider_client_create_apikey( app.pointer, pointer, namePtr, realmLib.addresses.realm_dart_apikey_callback, _createAsyncApikeyCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - ), - ); + ).raiseIfFalse(); return completer.future; }); @@ -146,14 +141,14 @@ class UserHandle extends HandleBase { return using((Arena arena) { final completer = Completer(); final nativeId = id.toNative(arena); - invokeGetBool(() => realmLib.realm_app_user_apikey_provider_client_fetch_apikey( + realmLib.realm_app_user_apikey_provider_client_fetch_apikey( app.pointer, pointer, nativeId.ref, realmLib.addresses.realm_dart_apikey_callback, _createAsyncApikeyCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - )); + ).raiseIfFalse(); return completer.future; }); @@ -162,13 +157,13 @@ class UserHandle extends HandleBase { Future> fetchAllApiKeys(AppHandle app) { return using((Arena arena) { final completer = Completer>(); - invokeGetBool(() => realmLib.realm_app_user_apikey_provider_client_fetch_apikeys( + realmLib.realm_app_user_apikey_provider_client_fetch_apikeys( app.pointer, pointer, realmLib.addresses.realm_dart_apikey_list_callback, _createAsyncApikeyListCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - )); + ).raiseIfFalse(); return completer.future; }); @@ -178,14 +173,14 @@ class UserHandle extends HandleBase { return using((Arena arena) { final completer = Completer(); final nativeId = id.toNative(arena); - invokeGetBool(() => realmLib.realm_app_user_apikey_provider_client_delete_apikey( + realmLib.realm_app_user_apikey_provider_client_delete_apikey( app.pointer, pointer, nativeId.ref, realmLib.addresses.realm_dart_void_completion_callback, createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - )); + ).raiseIfFalse(); return completer.future; }); @@ -196,16 +191,14 @@ class UserHandle extends HandleBase { final completer = Completer(); final nativeId = objectId.toNative(arena); - invokeGetBool( - () => realmLib.realm_app_user_apikey_provider_client_disable_apikey( + realmLib.realm_app_user_apikey_provider_client_disable_apikey( app.pointer, pointer, nativeId.ref, realmLib.addresses.realm_dart_void_completion_callback, createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - ), - ); + ).raiseIfFalse(); return completer.future; }); @@ -216,16 +209,14 @@ class UserHandle extends HandleBase { final completer = Completer(); final nativeId = objectId.toNative(arena); - invokeGetBool( - () => realmLib.realm_app_user_apikey_provider_client_enable_apikey( + realmLib.realm_app_user_apikey_provider_client_enable_apikey( app.pointer, pointer, nativeId.ref, realmLib.addresses.realm_dart_void_completion_callback, createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - ), - ); + ).raiseIfFalse(); return completer.future; }); From e262b1d44679fa885d6701893866c65182cb52d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Fri, 26 Apr 2024 18:22:04 +0200 Subject: [PATCH 54/68] Run melos custom_format --- packages/realm/bin/realm.dart | 2 +- .../lib/src/realm_common_base.dart | 2 +- .../realm_common/lib/src/realm_types.dart | 10 +- packages/realm_dart/bin/realm_dart.dart | 2 +- packages/realm_dart/lib/src/list.dart | 3 +- packages/realm_dart/lib/src/map.dart | 3 +- .../realm_dart/lib/src/native/app_handle.dart | 265 ++++++++++-------- .../lib/src/native/credentials_handle.dart | 30 +- .../lib/src/native/map_changes_handle.dart | 1 - .../realm_dart/lib/src/native/realm_core.dart | 22 +- .../lib/src/native/realm_handle.dart | 1 - .../realm_dart/lib/src/native/set_handle.dart | 16 +- .../src/native/subscription_set_handle.dart | 2 +- .../lib/src/native/user_handle.dart | 94 ++++--- packages/realm_dart/lib/src/realm_class.dart | 10 +- packages/realm_dart/lib/src/set.dart | 3 +- packages/realm_dart/test/test.dart | 1 - .../good_test_data/const_initializer.dart | 2 +- 18 files changed, 249 insertions(+), 220 deletions(-) diff --git a/packages/realm/bin/realm.dart b/packages/realm/bin/realm.dart index 80569db28..a8e88e123 100644 --- a/packages/realm/bin/realm.dart +++ b/packages/realm/bin/realm.dart @@ -1,6 +1,6 @@ // Copyright 2021 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 - import 'package:realm_dart/src/cli/main.dart' as x; + void main(List arguments) => x.main(arguments); diff --git a/packages/realm_common/lib/src/realm_common_base.dart b/packages/realm_common/lib/src/realm_common_base.dart index aecd823a4..742085801 100644 --- a/packages/realm_common/lib/src/realm_common_base.dart +++ b/packages/realm_common/lib/src/realm_common_base.dart @@ -129,4 +129,4 @@ class Backlink { /// The name of the field in the other class that links to this class. final Symbol fieldName; const Backlink(this.fieldName); -} \ No newline at end of file +} diff --git a/packages/realm_common/lib/src/realm_types.dart b/packages/realm_common/lib/src/realm_types.dart index 48ab76ebf..af031ae7e 100644 --- a/packages/realm_common/lib/src/realm_types.dart +++ b/packages/realm_common/lib/src/realm_types.dart @@ -86,11 +86,11 @@ enum RealmCollectionType { map; String get plural => switch (this) { - RealmCollectionType.list => 'lists', - RealmCollectionType.set => 'sets', - RealmCollectionType.map => 'maps', - _ => 'none' - }; + RealmCollectionType.list => 'lists', + RealmCollectionType.set => 'sets', + RealmCollectionType.map => 'maps', + _ => 'none', + }; } /// A base class of all Realm errors. diff --git a/packages/realm_dart/bin/realm_dart.dart b/packages/realm_dart/bin/realm_dart.dart index 80569db28..a8e88e123 100644 --- a/packages/realm_dart/bin/realm_dart.dart +++ b/packages/realm_dart/bin/realm_dart.dart @@ -1,6 +1,6 @@ // Copyright 2021 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 - import 'package:realm_dart/src/cli/main.dart' as x; + void main(List arguments) => x.main(arguments); diff --git a/packages/realm_dart/lib/src/list.dart b/packages/realm_dart/lib/src/list.dart index 3634a841c..187aa3c46 100644 --- a/packages/realm_dart/lib/src/list.dart +++ b/packages/realm_dart/lib/src/list.dart @@ -299,8 +299,7 @@ extension RealmListInternal on RealmList { throw RealmError("Can't add to list an embedded object that is already managed"); } - final objHandle = - insert || index >= length ? handle.insertEmbeddedAt(index) : handle.setEmbeddedAt(index); + final objHandle = insert || index >= length ? handle.insertEmbeddedAt(index) : handle.setEmbeddedAt(index); realm.manageEmbedded(objHandle, value); return; } diff --git a/packages/realm_dart/lib/src/map.dart b/packages/realm_dart/lib/src/map.dart index a0ef02874..99e47ddee 100644 --- a/packages/realm_dart/lib/src/map.dart +++ b/packages/realm_dart/lib/src/map.dart @@ -252,8 +252,7 @@ extension RealmMapInternal on RealmMap { static RealmMap createFromMap(Map map) => UnmanagedRealmMap._(map); - static RealmMap create(MapHandle handle, Realm realm, RealmObjectMetadata? metadata) => - ManagedRealmMap._(handle, realm, metadata); + static RealmMap create(MapHandle handle, Realm realm, RealmObjectMetadata? metadata) => ManagedRealmMap._(handle, realm, metadata); static void setValue(MapHandle handle, Realm realm, String key, Object? value, {bool update = false}) { try { diff --git a/packages/realm_dart/lib/src/native/app_handle.dart b/packages/realm_dart/lib/src/native/app_handle.dart index 80efaa44c..028537415 100644 --- a/packages/realm_dart/lib/src/native/app_handle.dart +++ b/packages/realm_dart/lib/src/native/app_handle.dart @@ -48,7 +48,7 @@ class AppHandle extends HandleBase { List _getUsers(Arena arena, {int expectedSize = 2}) { final actualCount = arena(); final usersPtr = arena>(expectedSize); - realmLib.realm_app_get_all_users(pointer, usersPtr, expectedSize, actualCount).raiseIfFalse(); + realmLib.realm_app_get_all_users(pointer, usersPtr, expectedSize, actualCount).raiseIfFalse(); if (expectedSize < actualCount.value) { // The supplied array was too small - resize it @@ -66,23 +66,26 @@ class AppHandle extends HandleBase { Future removeUser(UserHandle user) { final completer = Completer(); - realmLib.realm_app_remove_user( - pointer, - user.pointer, - realmLib.addresses.realm_dart_void_completion_callback, - createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ).raiseIfFalse("Remove user failed"); + realmLib + .realm_app_remove_user( + pointer, + user.pointer, + realmLib.addresses.realm_dart_void_completion_callback, + createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ) + .raiseIfFalse("Remove user failed"); return completer.future; } void switchUser(UserHandle user) { using((arena) { - realmLib.realm_app_switch_user( - pointer, - user.pointer, - nullptr, - ).raiseIfFalse("Switch user failed"); + realmLib + .realm_app_switch_user( + pointer, + user.pointer, + ) + .raiseIfFalse("Switch user failed"); }); } @@ -96,26 +99,30 @@ class AppHandle extends HandleBase { Future updateBaseUrl(Uri? baseUrl) { final completer = Completer(); using((arena) { - realmLib.realm_app_update_base_url( - pointer, - baseUrl.toString().toCharPtr(arena), - realmLib.addresses.realm_dart_void_completion_callback, - createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ).raiseIfFalse("Update base URL failed"); + realmLib + .realm_app_update_base_url( + pointer, + baseUrl?.toString().toCharPtr(arena) ?? nullptr, + realmLib.addresses.realm_dart_void_completion_callback, + createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ) + .raiseIfFalse("Update base URL failed"); }); return completer.future; } Future refreshCustomData(UserHandle user) { final completer = Completer(); - realmLib.realm_app_refresh_custom_data( - pointer, - user.pointer, - realmLib.addresses.realm_dart_void_completion_callback, - createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ).raiseIfFalse("Refresh custom data failed"); + realmLib + .realm_app_refresh_custom_data( + pointer, + user.pointer, + realmLib.addresses.realm_dart_void_completion_callback, + createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ) + .raiseIfFalse("Refresh custom data failed"); return completer.future; } @@ -125,27 +132,31 @@ class AppHandle extends HandleBase { Future logIn(CredentialsHandle credentials) async { final completer = Completer(); - realmLib.realm_app_log_in_with_credentials( - pointer, - credentials.pointer, - realmLib.addresses.realm_dart_user_completion_callback, - createAsyncUserCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ).raiseIfFalse("Login failed"); + realmLib + .realm_app_log_in_with_credentials( + pointer, + credentials.pointer, + realmLib.addresses.realm_dart_user_completion_callback, + createAsyncUserCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ) + .raiseIfFalse("Login failed"); return await completer.future; } Future registerUser(String email, String password) { final completer = Completer(); using((arena) { - realmLib.realm_app_email_password_provider_client_register_email( - pointer, - email.toCharPtr(arena), - password.toRealmString(arena).ref, - realmLib.addresses.realm_dart_void_completion_callback, - createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ).raiseIfFalse(); + realmLib + .realm_app_email_password_provider_client_register_email( + pointer, + email.toCharPtr(arena), + password.toRealmString(arena).ref, + realmLib.addresses.realm_dart_void_completion_callback, + createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ) + .raiseIfFalse(); }); return completer.future; } @@ -153,14 +164,16 @@ class AppHandle extends HandleBase { Future confirmUser(String token, String tokenId) async { final completer = Completer(); using((arena) { - realmLib.realm_app_email_password_provider_client_confirm_user( - pointer, - token.toCharPtr(arena), - tokenId.toCharPtr(arena), - realmLib.addresses.realm_dart_void_completion_callback, - createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ).raiseIfFalse(); + realmLib + .realm_app_email_password_provider_client_confirm_user( + pointer, + token.toCharPtr(arena), + tokenId.toCharPtr(arena), + realmLib.addresses.realm_dart_void_completion_callback, + createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ) + .raiseIfFalse(); }); return await completer.future; } @@ -168,13 +181,15 @@ class AppHandle extends HandleBase { Future resendConfirmation(String email) { final completer = Completer(); using((arena) { - realmLib.realm_app_email_password_provider_client_resend_confirmation_email( - pointer, - email.toCharPtr(arena), - realmLib.addresses.realm_dart_void_completion_callback, - createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ).raiseIfFalse(); + realmLib + .realm_app_email_password_provider_client_resend_confirmation_email( + pointer, + email.toCharPtr(arena), + realmLib.addresses.realm_dart_void_completion_callback, + createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ) + .raiseIfFalse(); }); return completer.future; } @@ -182,15 +197,17 @@ class AppHandle extends HandleBase { Future completeResetPassword(String password, String token, String tokenId) { final completer = Completer(); using((arena) { - realmLib.realm_app_email_password_provider_client_reset_password( - pointer, - password.toRealmString(arena).ref, - token.toCharPtr(arena), - tokenId.toCharPtr(arena), - realmLib.addresses.realm_dart_void_completion_callback, - createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ).raiseIfFalse(); + realmLib + .realm_app_email_password_provider_client_reset_password( + pointer, + password.toRealmString(arena).ref, + token.toCharPtr(arena), + tokenId.toCharPtr(arena), + realmLib.addresses.realm_dart_void_completion_callback, + createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ) + .raiseIfFalse(); }); return completer.future; } @@ -198,13 +215,15 @@ class AppHandle extends HandleBase { Future requestResetPassword(String email) { final completer = Completer(); using((arena) { - realmLib.realm_app_email_password_provider_client_send_reset_password_email( - pointer, - email.toCharPtr(arena), - realmLib.addresses.realm_dart_void_completion_callback, - createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ).raiseIfFalse(); + realmLib + .realm_app_email_password_provider_client_send_reset_password_email( + pointer, + email.toCharPtr(arena), + realmLib.addresses.realm_dart_void_completion_callback, + createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ) + .raiseIfFalse(); }); return completer.future; } @@ -212,15 +231,17 @@ class AppHandle extends HandleBase { Future callResetPasswordFunction(String email, String password, String? argsAsJSON) { final completer = Completer(); using((arena) { - realmLib.realm_app_email_password_provider_client_call_reset_password_function( - pointer, - email.toCharPtr(arena), - password.toRealmString(arena).ref, - argsAsJSON != null ? argsAsJSON.toCharPtr(arena) : nullptr, - realmLib.addresses.realm_dart_void_completion_callback, - createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ).raiseIfFalse(); + realmLib + .realm_app_email_password_provider_client_call_reset_password_function( + pointer, + email.toCharPtr(arena), + password.toRealmString(arena).ref, + argsAsJSON != null ? argsAsJSON.toCharPtr(arena) : nullptr, + realmLib.addresses.realm_dart_void_completion_callback, + createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ) + .raiseIfFalse(); }); return completer.future; } @@ -228,13 +249,15 @@ class AppHandle extends HandleBase { Future retryCustomConfirmationFunction(String email) { final completer = Completer(); using((arena) { - realmLib.realm_app_email_password_provider_client_retry_custom_confirmation( - pointer, - email.toCharPtr(arena), - realmLib.addresses.realm_dart_void_completion_callback, - createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ).raiseIfFalse(); + realmLib + .realm_app_email_password_provider_client_retry_custom_confirmation( + pointer, + email.toCharPtr(arena), + realmLib.addresses.realm_dart_void_completion_callback, + createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ) + .raiseIfFalse(); }); return completer.future; } @@ -242,44 +265,52 @@ class AppHandle extends HandleBase { Future logOut(UserHandle? user) { final completer = Completer(); if (user == null) { - realmLib.realm_app_log_out_current_user( - pointer, - realmLib.addresses.realm_dart_void_completion_callback, - createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ).raiseIfFalse("Logout failed"); + realmLib + .realm_app_log_out_current_user( + pointer, + realmLib.addresses.realm_dart_void_completion_callback, + createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ) + .raiseIfFalse("Logout failed"); } else { - realmLib.realm_app_log_out( - pointer, - user.pointer, - realmLib.addresses.realm_dart_void_completion_callback, - createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ).raiseIfFalse("Logout failed"); + realmLib + .realm_app_log_out( + pointer, + user.pointer, + realmLib.addresses.realm_dart_void_completion_callback, + createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ) + .raiseIfFalse("Logout failed"); } return completer.future; } Future deleteUser(UserHandle user) { final completer = Completer(); - realmLib.realm_app_delete_user( - pointer, - user.pointer, - realmLib.addresses.realm_dart_void_completion_callback, - createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ).raiseIfFalse("Delete user failed"); + realmLib + .realm_app_delete_user( + pointer, + user.pointer, + realmLib.addresses.realm_dart_void_completion_callback, + createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ) + .raiseIfFalse("Delete user failed"); return completer.future; } bool immediatelyRunFileActions(String realmPath) { return using((arena) { final didRun = arena(); - realmLib.realm_sync_immediately_run_file_actions( - pointer, - realmPath.toCharPtr(arena), - didRun, - ).raiseIfFalse("An error occurred while resetting the Realm. Check if the file is in use: '$realmPath'"); + realmLib + .realm_sync_immediately_run_file_actions( + pointer, + realmPath.toCharPtr(arena), + didRun, + ) + .raiseIfFalse("An error occurred while resetting the Realm. Check if the file is in use: '$realmPath'"); return didRun.value; }); } @@ -287,7 +318,8 @@ class AppHandle extends HandleBase { Future callAppFunction(UserHandle user, String functionName, String? argsAsJSON) { return using((arena) { final completer = Completer(); - realmLib.realm_app_call_function( + realmLib + .realm_app_call_function( pointer, user.pointer, functionName.toCharPtr(arena), @@ -296,7 +328,8 @@ class AppHandle extends HandleBase { realmLib.addresses.realm_dart_return_string_callback, createAsyncFunctionCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - ).raiseIfFalse(); + ) + .raiseIfFalse(); return completer.future; }); } diff --git a/packages/realm_dart/lib/src/native/credentials_handle.dart b/packages/realm_dart/lib/src/native/credentials_handle.dart index 9feb3b975..78a86b557 100644 --- a/packages/realm_dart/lib/src/native/credentials_handle.dart +++ b/packages/realm_dart/lib/src/native/credentials_handle.dart @@ -13,68 +13,59 @@ import 'realm_core.dart'; // TODO: Remove this import import 'realm_library.dart'; class CredentialsHandle extends HandleBase { - CredentialsHandle(Pointer pointer) - : super(pointer, 16); + CredentialsHandle(Pointer pointer) : super(pointer, 16); factory CredentialsHandle.anonymous(bool reuseCredentials) { - return CredentialsHandle( - realmLib.realm_app_credentials_new_anonymous(reuseCredentials)); + return CredentialsHandle(realmLib.realm_app_credentials_new_anonymous(reuseCredentials)); } factory CredentialsHandle.emailPassword(String email, String password) { return using((arena) { final emailPtr = email.toCharPtr(arena); final passwordPtr = password.toRealmString(arena); - return CredentialsHandle(realmLib - .realm_app_credentials_new_email_password(emailPtr, passwordPtr.ref)); + return CredentialsHandle(realmLib.realm_app_credentials_new_email_password(emailPtr, passwordPtr.ref)); }); } factory CredentialsHandle.jwt(String token) { return using((arena) { final tokenPtr = token.toCharPtr(arena); - return CredentialsHandle( - realmLib.realm_app_credentials_new_jwt(tokenPtr)); + return CredentialsHandle(realmLib.realm_app_credentials_new_jwt(tokenPtr)); }); } factory CredentialsHandle.apple(String idToken) { return using((arena) { final idTokenPtr = idToken.toCharPtr(arena); - return CredentialsHandle( - realmLib.realm_app_credentials_new_apple(idTokenPtr)); + return CredentialsHandle(realmLib.realm_app_credentials_new_apple(idTokenPtr)); }); } factory CredentialsHandle.facebook(String accessToken) { return using((arena) { final accessTokenPtr = accessToken.toCharPtr(arena); - return CredentialsHandle( - realmLib.realm_app_credentials_new_facebook(accessTokenPtr)); + return CredentialsHandle(realmLib.realm_app_credentials_new_facebook(accessTokenPtr)); }); } factory CredentialsHandle.googleIdToken(String idToken) { return using((arena) { final idTokenPtr = idToken.toCharPtr(arena); - return CredentialsHandle( - realmLib.realm_app_credentials_new_google_id_token(idTokenPtr)); + return CredentialsHandle(realmLib.realm_app_credentials_new_google_id_token(idTokenPtr)); }); } factory CredentialsHandle.googleAuthCode(String authCode) { return using((arena) { final authCodePtr = authCode.toCharPtr(arena); - return CredentialsHandle( - realmLib.realm_app_credentials_new_google_auth_code(authCodePtr)); + return CredentialsHandle(realmLib.realm_app_credentials_new_google_auth_code(authCodePtr)); }); } factory CredentialsHandle.function(String payload) { return using((arena) { final payloadPtr = payload.toCharPtr(arena); - final credentialsPtr = - realmLib.realm_app_credentials_new_function(payloadPtr).raiseIfNull(); + final credentialsPtr = realmLib.realm_app_credentials_new_function(payloadPtr).raiseIfNull(); return CredentialsHandle(credentialsPtr); }); } @@ -82,8 +73,7 @@ class CredentialsHandle extends HandleBase { factory CredentialsHandle.apiKey(String key) { return using((arena) { final keyPtr = key.toCharPtr(arena); - return CredentialsHandle( - realmLib.realm_app_credentials_new_api_key(keyPtr)); + return CredentialsHandle(realmLib.realm_app_credentials_new_api_key(keyPtr)); }); } diff --git a/packages/realm_dart/lib/src/native/map_changes_handle.dart b/packages/realm_dart/lib/src/native/map_changes_handle.dart index 79472e34d..4b6291397 100644 --- a/packages/realm_dart/lib/src/native/map_changes_handle.dart +++ b/packages/realm_dart/lib/src/native/map_changes_handle.dart @@ -1,7 +1,6 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 - import 'dart:ffi'; import 'package:ffi/ffi.dart'; diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 2710f8c2f..2e93feb00 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -342,28 +342,24 @@ class _RealmCore { AsyncOpenTaskHandle handle, RealmAsyncOpenProgressNotificationsController controller) { final callback = Pointer.fromFunction(syncProgressCallback); final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); - final tokenPtr = realmLib.realm_async_open_task_register_download_progress_notifier( + final tokenPtr = realmLib + .realm_async_open_task_register_download_progress_notifier( handle.pointer, realmLib.addresses.realm_dart_sync_progress_callback, userdata.cast(), realmLib.addresses.realm_dart_userdata_async_free, - ).raiseIfNull(); + ) + .raiseIfNull(); return AsyncOpenTaskProgressNotificationTokenHandle(tokenPtr); } - RealmSchema readSchema(Realm realm) => realm.handle.readSchema(); - void deleteRealmFiles(String path) { using((Arena arena) { final realmDeleted = arena(); - realmLib.realm_delete_files(path.toCharPtr(arena), realmDeleted).raiseIfFalse("Error deleting realm at path $path"); + realmLib.realm_delete_files(path.toCharPtr(arena), realmDeleted).raiseIfFalse("Error deleting realm at path $path"); }); } - RealmObjectMetadata getObjectMetadata(Realm realm, SchemaObject schema) => realm.handle.getObjectMetadata(schema); - - Map getPropertiesMetadata(Realm realm, int classKey, String? primaryKeyName) => realm.handle.getPropertiesMetadata(classKey, primaryKeyName); - // For debugging // ignore: unused_element int get _threadId => realmLib.realm_dart_get_thread_id(); @@ -403,7 +399,7 @@ class _RealmCore { AppHandle? getApp(String id, String? baseUrl) { return using((arena) { final outApp = arena>(); - realmLib.realm_app_get_cached(id.toCharPtr(arena), baseUrl == null ? nullptr : baseUrl.toCharPtr(arena), outApp).raiseIfFalse(); + realmLib.realm_app_get_cached(id.toCharPtr(arena), baseUrl == null ? nullptr : baseUrl.toCharPtr(arena), outApp).raiseIfFalse(); return outApp.value == nullptr ? null : AppHandle(outApp.value); }); } @@ -473,7 +469,8 @@ class _RealmCore { Future callAppFunction(App app, User user, String functionName, String? argsAsJSON) { return using((arena) { final completer = Completer(); - realmLib.realm_app_call_function( + realmLib + .realm_app_call_function( app.handle.pointer, user.handle.pointer, functionName.toCharPtr(arena), @@ -482,7 +479,8 @@ class _RealmCore { realmLib.addresses.realm_dart_return_string_callback, createAsyncFunctionCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - ).raiseIfFalse(); + ) + .raiseIfFalse(); return completer.future; }); } diff --git a/packages/realm_dart/lib/src/native/realm_handle.dart b/packages/realm_dart/lib/src/native/realm_handle.dart index de236ba79..55d2b4a09 100644 --- a/packages/realm_dart/lib/src/native/realm_handle.dart +++ b/packages/realm_dart/lib/src/native/realm_handle.dart @@ -12,7 +12,6 @@ import '../logging.dart'; import '../realm_class.dart'; import '../realm_object.dart'; import 'config_handle.dart'; -import 'convert.dart'; import 'error_handling.dart'; import 'handle_base.dart'; import 'object_handle.dart'; diff --git a/packages/realm_dart/lib/src/native/set_handle.dart b/packages/realm_dart/lib/src/native/set_handle.dart index 994a48d70..0ddcef6fa 100644 --- a/packages/realm_dart/lib/src/native/set_handle.dart +++ b/packages/realm_dart/lib/src/native/set_handle.dart @@ -49,7 +49,7 @@ class SetHandle extends RootedHandleBase { final realmValue = value.toNative(arena); final outIndex = arena(); final outInserted = arena(); - realmLib.realm_set_insert(pointer, realmValue.ref, outIndex, outInserted).raiseIfFalse(); + realmLib.realm_set_insert(pointer, realmValue.ref, outIndex, outInserted).raiseIfFalse(); return outInserted.value; }); } @@ -58,7 +58,7 @@ class SetHandle extends RootedHandleBase { Object? elementAt(Realm realm, int index) { return using((Arena arena) { final realmValue = arena(); - realmLib.realm_set_get(pointer, index, realmValue).raiseIfFalse(); + realmLib.realm_set_get(pointer, index, realmValue).raiseIfFalse(); final result = realmValue.toDartValue( realm, () => throw RealmException('Sets cannot contain collections'), @@ -74,7 +74,7 @@ class SetHandle extends RootedHandleBase { final realmValue = value.toNative(arena); final outIndex = arena(); final outFound = arena(); - realmLib.realm_set_find(pointer, realmValue.ref, outIndex, outFound).raiseIfFalse(); + realmLib.realm_set_find(pointer, realmValue.ref, outIndex, outFound).raiseIfFalse(); return outFound.value; }); } @@ -84,19 +84,19 @@ class SetHandle extends RootedHandleBase { // TODO: do we support sets containing mixed collections final realmValue = value.toNative(arena); final outErased = arena(); - realmLib.realm_set_erase(pointer, realmValue.ref, outErased).raiseIfFalse(); + realmLib.realm_set_erase(pointer, realmValue.ref, outErased).raiseIfFalse(); return outErased.value; }); } void clear() { - realmLib.realm_set_clear(pointer).raiseIfFalse(); + realmLib.realm_set_clear(pointer).raiseIfFalse(); } int get size { return using((Arena arena) { final outSize = arena(); - realmLib.realm_set_size(pointer, outSize).raiseIfFalse(); + realmLib.realm_set_size(pointer, outSize).raiseIfFalse(); return outSize.value; }); } @@ -106,13 +106,13 @@ class SetHandle extends RootedHandleBase { } void deleteAll() { - realmLib.realm_set_remove_all(pointer).raiseIfFalse(); + realmLib.realm_set_remove_all(pointer).raiseIfFalse(); } SetHandle? resolveIn(RealmHandle frozenRealm) { return using((Arena arena) { final resultPtr = arena>(); - realmLib.realm_set_resolve_in(pointer, frozenRealm.pointer, resultPtr).raiseIfFalse(); + realmLib.realm_set_resolve_in(pointer, frozenRealm.pointer, resultPtr).raiseIfFalse(); return resultPtr == nullptr ? null : SetHandle(resultPtr.value, root); }); } diff --git a/packages/realm_dart/lib/src/native/subscription_set_handle.dart b/packages/realm_dart/lib/src/native/subscription_set_handle.dart index 3f5f0706d..0725f6626 100644 --- a/packages/realm_dart/lib/src/native/subscription_set_handle.dart +++ b/packages/realm_dart/lib/src/native/subscription_set_handle.dart @@ -25,7 +25,7 @@ class SubscriptionSetHandle extends RootedHandleBase pointer, RealmHandle root) : super(root, pointer, 128); - void refresh() => realmLib.realm_sync_subscription_set_refresh(pointer).raiseIfFalse(); + void refresh() => realmLib.realm_sync_subscription_set_refresh(pointer).raiseIfFalse(); int get size => realmLib.realm_sync_subscription_set_size(pointer); diff --git a/packages/realm_dart/lib/src/native/user_handle.dart b/packages/realm_dart/lib/src/native/user_handle.dart index 0573f02ea..4e217f1a2 100644 --- a/packages/realm_dart/lib/src/native/user_handle.dart +++ b/packages/realm_dart/lib/src/native/user_handle.dart @@ -48,7 +48,7 @@ class UserHandle extends HandleBase { List _userGetIdentities(Arena arena, {int expectedSize = 2}) { final actualCount = arena(); final identitiesPtr = arena(expectedSize); - realmLib.realm_user_get_all_identities(pointer, identitiesPtr, expectedSize, actualCount).raiseIfFalse(); + realmLib.realm_user_get_all_identities(pointer, identitiesPtr, expectedSize, actualCount).raiseIfFalse(); if (expectedSize < actualCount.value) { // The supplied array was too small - resize it @@ -68,7 +68,7 @@ class UserHandle extends HandleBase { } Future logOut() async { - realmLib.realm_user_log_out(pointer).raiseIfFalse("Logout failed"); + realmLib.realm_user_log_out(pointer).raiseIfFalse("Logout failed"); } String? get deviceId { @@ -109,14 +109,16 @@ class UserHandle extends HandleBase { Future linkCredentials(AppHandle app, CredentialsHandle credentials) { final completer = Completer(); - realmLib.realm_app_link_user( - app.pointer, - pointer, - credentials.pointer, - realmLib.addresses.realm_dart_user_completion_callback, - createAsyncUserCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ).raiseIfFalse("Link credentials failed"); + realmLib + .realm_app_link_user( + app.pointer, + pointer, + credentials.pointer, + realmLib.addresses.realm_dart_user_completion_callback, + createAsyncUserCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ) + .raiseIfFalse("Link credentials failed"); return completer.future; } @@ -124,14 +126,16 @@ class UserHandle extends HandleBase { return using((Arena arena) { final namePtr = name.toCharPtr(arena); final completer = Completer(); - realmLib.realm_app_user_apikey_provider_client_create_apikey( - app.pointer, - pointer, - namePtr, - realmLib.addresses.realm_dart_apikey_callback, - _createAsyncApikeyCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ).raiseIfFalse(); + realmLib + .realm_app_user_apikey_provider_client_create_apikey( + app.pointer, + pointer, + namePtr, + realmLib.addresses.realm_dart_apikey_callback, + _createAsyncApikeyCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ) + .raiseIfFalse(); return completer.future; }); @@ -141,14 +145,16 @@ class UserHandle extends HandleBase { return using((Arena arena) { final completer = Completer(); final nativeId = id.toNative(arena); - realmLib.realm_app_user_apikey_provider_client_fetch_apikey( + realmLib + .realm_app_user_apikey_provider_client_fetch_apikey( app.pointer, pointer, nativeId.ref, realmLib.addresses.realm_dart_apikey_callback, _createAsyncApikeyCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - ).raiseIfFalse(); + ) + .raiseIfFalse(); return completer.future; }); @@ -157,13 +163,15 @@ class UserHandle extends HandleBase { Future> fetchAllApiKeys(AppHandle app) { return using((Arena arena) { final completer = Completer>(); - realmLib.realm_app_user_apikey_provider_client_fetch_apikeys( + realmLib + .realm_app_user_apikey_provider_client_fetch_apikeys( app.pointer, pointer, realmLib.addresses.realm_dart_apikey_list_callback, _createAsyncApikeyListCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - ).raiseIfFalse(); + ) + .raiseIfFalse(); return completer.future; }); @@ -173,14 +181,16 @@ class UserHandle extends HandleBase { return using((Arena arena) { final completer = Completer(); final nativeId = id.toNative(arena); - realmLib.realm_app_user_apikey_provider_client_delete_apikey( + realmLib + .realm_app_user_apikey_provider_client_delete_apikey( app.pointer, pointer, nativeId.ref, realmLib.addresses.realm_dart_void_completion_callback, createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, - ).raiseIfFalse(); + ) + .raiseIfFalse(); return completer.future; }); @@ -191,14 +201,16 @@ class UserHandle extends HandleBase { final completer = Completer(); final nativeId = objectId.toNative(arena); - realmLib.realm_app_user_apikey_provider_client_disable_apikey( - app.pointer, - pointer, - nativeId.ref, - realmLib.addresses.realm_dart_void_completion_callback, - createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ).raiseIfFalse(); + realmLib + .realm_app_user_apikey_provider_client_disable_apikey( + app.pointer, + pointer, + nativeId.ref, + realmLib.addresses.realm_dart_void_completion_callback, + createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ) + .raiseIfFalse(); return completer.future; }); @@ -209,14 +221,16 @@ class UserHandle extends HandleBase { final completer = Completer(); final nativeId = objectId.toNative(arena); - realmLib.realm_app_user_apikey_provider_client_enable_apikey( - app.pointer, - pointer, - nativeId.ref, - realmLib.addresses.realm_dart_void_completion_callback, - createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ).raiseIfFalse(); + realmLib + .realm_app_user_apikey_provider_client_enable_apikey( + app.pointer, + pointer, + nativeId.ref, + realmLib.addresses.realm_dart_void_completion_callback, + createAsyncCallbackUserdata(completer), + realmLib.addresses.realm_dart_userdata_async_free, + ) + .raiseIfFalse(); return completer.future; }); diff --git a/packages/realm_dart/lib/src/realm_class.dart b/packages/realm_dart/lib/src/realm_class.dart index 401146751..28e7c013c 100644 --- a/packages/realm_dart/lib/src/realm_class.dart +++ b/packages/realm_dart/lib/src/realm_class.dart @@ -215,8 +215,8 @@ class Realm implements Finalizable { } void _populateMetadata() { - schema = config.schemaObjects.isNotEmpty ? RealmSchema(config.schemaObjects) : realmCore.readSchema(this); - _metadata = RealmMetadata._(schema.map((c) => realmCore.getObjectMetadata(this, c))); + schema = config.schemaObjects.isNotEmpty ? RealmSchema(config.schemaObjects) : handle.readSchema(); + _metadata = RealmMetadata._(schema.map((c) => handle.getObjectMetadata(c))); } /// Deletes all files associated with a `Realm` located at given [path] @@ -627,7 +627,7 @@ class Realm implements Finalizable { } void _updateSchema() { - final newSchema = realmCore.readSchema(this); + final newSchema = handle.readSchema(); for (final listener in _schemaChangeListeners) { listener.add(RealmSchemaChanges._(schema, newSchema)); } @@ -636,11 +636,11 @@ class Realm implements Finalizable { final existing = schema.firstWhereOrNull((s) => s.name == schemaObject.name); if (existing == null) { schema.add(schemaObject); - final meta = realmCore.getObjectMetadata(this, schemaObject); + final meta = handle.getObjectMetadata(schemaObject); metadata._add(meta); } else if (schemaObject.length > existing.length) { final existingMeta = metadata.getByName(schemaObject.name); - final propertyMeta = realmCore.getPropertiesMetadata(this, existingMeta.classKey, existingMeta.primaryKey); + final propertyMeta = handle.getPropertiesMetadata(existingMeta.classKey, existingMeta.primaryKey); for (final property in schemaObject) { final existingProp = existing.firstWhereOrNull((e) => e.mapTo == property.mapTo); if (existingProp == null) { diff --git a/packages/realm_dart/lib/src/set.dart b/packages/realm_dart/lib/src/set.dart index a0bd4f573..422c35dc5 100644 --- a/packages/realm_dart/lib/src/set.dart +++ b/packages/realm_dart/lib/src/set.dart @@ -295,8 +295,7 @@ extension RealmSetInternal on RealmSet { return result; } - static RealmSet create(SetHandle handle, Realm realm, RealmObjectMetadata? metadata) => - ManagedRealmSet._(handle, realm, metadata); + static RealmSet create(SetHandle handle, Realm realm, RealmObjectMetadata? metadata) => ManagedRealmSet._(handle, realm, metadata); } class _RealmSetIterator implements Iterator { diff --git a/packages/realm_dart/test/test.dart b/packages/realm_dart/test/test.dart index 9d34fcf9a..7dc8eae1c 100644 --- a/packages/realm_dart/test/test.dart +++ b/packages/realm_dart/test/test.dart @@ -415,7 +415,6 @@ const int minInt = -9223372036854775808; const int jsMaxInt = 9007199254740991; const int jsMinInt = -9007199254740991; - void xtest(String? name, dynamic Function() testFunction, {dynamic skip, Map? onPlatform}) { test(name, testFunction, skip: "Test is disabled"); } diff --git a/packages/realm_generator/test/good_test_data/const_initializer.dart b/packages/realm_generator/test/good_test_data/const_initializer.dart index 9fcf7b601..fba9d4ca0 100644 --- a/packages/realm_generator/test/good_test_data/const_initializer.dart +++ b/packages/realm_generator/test/good_test_data/const_initializer.dart @@ -13,7 +13,7 @@ class _ConstInitializer { int minusMinusOne = -(-1); int add = 1 + 1; int identifier = myConst; - + double infinity = double.infinity; double nan = double.nan; double negativeInfinity = double.negativeInfinity; From f3111292eb28efb33838d6add63d01001b56a765 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Fri, 3 May 2024 12:42:21 +0200 Subject: [PATCH 55/68] Move callAppFunction stuff --- .../realm_dart/lib/src/native/app_handle.dart | 41 ++++++- .../realm_dart/lib/src/native/realm_core.dart | 110 ------------------ .../lib/src/native/user_handle.dart | 34 ++++++ packages/realm_dart/lib/src/user.dart | 2 +- 4 files changed, 75 insertions(+), 112 deletions(-) diff --git a/packages/realm_dart/lib/src/native/app_handle.dart b/packages/realm_dart/lib/src/native/app_handle.dart index 028537415..cac55fe55 100644 --- a/packages/realm_dart/lib/src/native/app_handle.dart +++ b/packages/realm_dart/lib/src/native/app_handle.dart @@ -487,7 +487,7 @@ Pointer createAsyncFunctionCallbackUserdata(Completer completer) { Pointer, Pointer, Pointer, - )>(callAppFunctionCallback); + )>(_callAppFunctionCallback); final userdata = realmLib.realm_dart_userdata_async_new( completer, @@ -498,6 +498,45 @@ Pointer createAsyncFunctionCallbackUserdata(Completer completer) { return userdata.cast(); } +void _callAppFunctionCallback(Pointer userdata, Pointer response, Pointer error) { + final Completer completer = userdata.toObject(); + + if (error != nullptr) { + completer.completeWithAppError(error); + return; + } + + final stringResponse = response.cast().toRealmDartString()!; + completer.complete(stringResponse); +} + +Pointer createAsyncCallbackUserdata(Completer completer) { + final callback = Pointer.fromFunction< + Void Function( + Pointer, + Pointer, + )>(_voidCompletionCallback); + + final userdata = realmLib.realm_dart_userdata_async_new( + completer, + callback.cast(), + scheduler.handle.pointer, + ); + + return userdata.cast(); +} + +void _voidCompletionCallback(Pointer userdata, Pointer error) { + final Completer completer = userdata.toObject(); + + if (error != nullptr) { + completer.completeWithAppError(error); + return; + } + + completer.complete(); +} + class _AppConfigHandle extends HandleBase { _AppConfigHandle(Pointer pointer) : super(pointer, 8); } diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 2e93feb00..8aadacfab 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -34,7 +34,6 @@ import 'realm_handle.dart'; import 'realm_library.dart'; import 'rooted_handle.dart'; import 'session_handle.dart'; -import 'user_handle.dart'; final _pluginLib = () { if (!isFlutterPlatform) { @@ -128,67 +127,6 @@ void guardSynchronousCallback(FutureOr Function() callback, Pointer } } -Pointer createAsyncUserCallbackUserdata(Completer completer) { - final callback = Pointer.fromFunction< - Void Function( - Pointer, - Pointer, - Pointer, - )>(appUserCompletionCallback); - - final userdata = realmLib.realm_dart_userdata_async_new( - completer, - callback.cast(), - scheduler.handle.pointer, - ); - - return userdata.cast(); -} - -void appUserCompletionCallback(Pointer userdata, Pointer user, Pointer error) { - final Completer completer = userdata.toObject(); - - if (error != nullptr) { - completer.completeWithAppError(error); - return; - } - - user = realmLib.realm_clone(user.cast()).cast(); // take an extra reference to the user object - if (user == nullptr) { - completer.completeError(RealmException("Error while cloning user object.")); - return; - } - - completer.complete(UserHandle(user.cast())); -} - -void voidCompletionCallback(Pointer userdata, Pointer error) { - final Completer completer = userdata.toObject(); - - if (error != nullptr) { - completer.completeWithAppError(error); - return; - } - - completer.complete(); -} - -Pointer createAsyncCallbackUserdata(Completer completer) { - final callback = Pointer.fromFunction< - Void Function( - Pointer, - Pointer, - )>(voidCompletionCallback); - - final userdata = realmLib.realm_dart_userdata_async_new( - completer, - callback.cast(), - scheduler.handle.pointer, - ); - - return userdata.cast(); -} - void createCollection(Realm realm, RealmValue value, Pointer Function() createList, Pointer Function() createMap) { CollectionHandleBase? collectionHandle; try { @@ -249,18 +187,6 @@ void collectionChangeCallback(Pointer userdata, Pointer userdata, Pointer response, Pointer error) { - final Completer completer = userdata.toObject(); - - if (error != nullptr) { - completer.completeWithAppError(error); - return; - } - - final stringResponse = response.cast().toRealmDartString()!; - completer.complete(stringResponse); -} - // All access to Realm Core functionality goes through this class class _RealmCore { // ignore: unused_field @@ -449,42 +375,6 @@ class _RealmCore { } } - Pointer createAsyncFunctionCallbackUserdata(Completer completer) { - final callback = Pointer.fromFunction< - Void Function( - Pointer, - Pointer, - Pointer, - )>(callAppFunctionCallback); - - final userdata = realmLib.realm_dart_userdata_async_new( - completer, - callback.cast(), - scheduler.handle.pointer, - ); - - return userdata.cast(); - } - - Future callAppFunction(App app, User user, String functionName, String? argsAsJSON) { - return using((arena) { - final completer = Completer(); - realmLib - .realm_app_call_function( - app.handle.pointer, - user.handle.pointer, - functionName.toCharPtr(arena), - argsAsJSON?.toCharPtr(arena) ?? nullptr, - nullptr, - realmLib.addresses.realm_dart_return_string_callback, - createAsyncFunctionCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ) - .raiseIfFalse(); - return completer.future; - }); - } - void setLogLevel(LogLevel level, {required LogCategory category}) { using((arena) { realmLib.realm_set_log_level_category(category.toString().toCharPtr(arena), level.index); diff --git a/packages/realm_dart/lib/src/native/user_handle.dart b/packages/realm_dart/lib/src/native/user_handle.dart index 4e217f1a2..9fc14b992 100644 --- a/packages/realm_dart/lib/src/native/user_handle.dart +++ b/packages/realm_dart/lib/src/native/user_handle.dart @@ -259,6 +259,40 @@ void _userChangeCallback(Object userdata, int data) { controller.onUserChanged(); } +Pointer createAsyncUserCallbackUserdata(Completer completer) { + final callback = Pointer.fromFunction< + Void Function( + Pointer, + Pointer, + Pointer, + )>(_appUserCompletionCallback); + + final userdata = realmLib.realm_dart_userdata_async_new( + completer, + callback.cast(), + scheduler.handle.pointer, + ); + + return userdata.cast(); +} + +void _appUserCompletionCallback(Pointer userdata, Pointer user, Pointer error) { + final Completer completer = userdata.toObject(); + + if (error != nullptr) { + completer.completeWithAppError(error); + return; + } + + user = realmLib.realm_clone(user.cast()).cast(); // take an extra reference to the user object + if (user == nullptr) { + completer.completeError(RealmException("Error while cloning user object.")); + return; + } + + completer.complete(UserHandle(user.cast())); +} + Pointer _createAsyncApikeyCallbackUserdata(Completer completer) { final callback = Pointer.fromFunction< Void Function( diff --git a/packages/realm_dart/lib/src/user.dart b/packages/realm_dart/lib/src/user.dart index 48164d12c..ea652b286 100644 --- a/packages/realm_dart/lib/src/user.dart +++ b/packages/realm_dart/lib/src/user.dart @@ -356,7 +356,7 @@ class FunctionsClient { Future call(String name, [List functionArgs = const []]) async { _user._ensureLoggedIn('call Atlas function'); final args = jsonEncode(functionArgs); - final response = await realmCore.callAppFunction(_user.app, _user, name, args); + final response = await _user.app.handle.callAppFunction(_user.handle, name, args); return jsonDecode(response); } } From 5c8be2e4e782e26328b08c5c0fbd247addf312e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Fri, 3 May 2024 14:01:21 +0200 Subject: [PATCH 56/68] Refactor equals --- .../lib/src/native/handle_base.dart | 8 +++++ .../lib/src/native/object_handle.dart | 17 ++++++++++ .../realm_dart/lib/src/native/realm_core.dart | 32 +------------------ packages/realm_dart/lib/src/realm_class.dart | 2 +- packages/realm_dart/lib/src/realm_object.dart | 4 +-- packages/realm_dart/lib/src/user.dart | 3 +- 6 files changed, 30 insertions(+), 36 deletions(-) diff --git a/packages/realm_dart/lib/src/native/handle_base.dart b/packages/realm_dart/lib/src/native/handle_base.dart index df5c07ad6..e15b0d78a 100644 --- a/packages/realm_dart/lib/src/native/handle_base.dart +++ b/packages/realm_dart/lib/src/native/handle_base.dart @@ -77,4 +77,12 @@ abstract class HandleBase implements Finalizable { _tearDownFinalizationTrace(this, pointer); } } + + @override + // ignore: hash_and_equals + bool operator ==(Object other) => other is HandleBase + ? pointer == other.pointer + ? true + : realmLib.realm_equals(pointer.cast(), other.pointer.cast()) + : false; } diff --git a/packages/realm_dart/lib/src/native/object_handle.dart b/packages/realm_dart/lib/src/native/object_handle.dart index 98cb16fc3..42aae6935 100644 --- a/packages/realm_dart/lib/src/native/object_handle.dart +++ b/packages/realm_dart/lib/src/native/object_handle.dart @@ -42,6 +42,11 @@ class ObjectHandle extends RootedHandleBase { bool get isValid => realmLib.realm_object_is_valid(pointer); + Link get asLink { + final realmLink = realmLib.realm_object_as_link(pointer); + return Link(realmLink); + } + // TODO: avoid taking the [realm] parameter Object? getValue(Realm realm, int propertyKey) { return using((Arena arena) { @@ -150,6 +155,18 @@ class ObjectHandle extends RootedHandleBase { return realmLib.realm_create_key_path_array(root.pointer, classKey, length, keypathsNative).raiseIfNull(); }); } + + @override + // equals handled by HandleBase + // ignore: hash_and_equals + int get hashCode => asLink.hash; +} + +extension type Link(realm_link_t link) { + int get targetKey => link.target; + int get classKey => link.target_table; + + int get hash => Object.hash(targetKey, classKey); } void _objectChangeCallback(Pointer userdata, Pointer data) { diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 8aadacfab..7ca5ba3c8 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -290,28 +290,6 @@ class _RealmCore { // ignore: unused_element int get _threadId => realmLib.realm_dart_get_thread_id(); - _RealmLinkHandle _getObjectAsLink(RealmObjectBase object) { - final realmLink = realmLib.realm_object_as_link(object.handle.pointer); - return _RealmLinkHandle(realmLink); - } - - bool _equals(HandleBase first, HandleBase second) { - return realmLib.realm_equals(first.pointer.cast(), second.pointer.cast()); - } - - bool objectEquals(RealmObjectBase first, RealmObjectBase second) => _equals(first.handle, second.handle); - bool realmEquals(Realm first, Realm second) => _equals(first.handle, second.handle); - bool userEquals(User first, User second) => _equals(first.handle, second.handle); - - int objectGetHashCode(RealmObjectBase value) { - final link = realmCore._getObjectAsLink(value); - - var hashCode = -986587137; - hashCode = (hashCode * -1521134295) + link.classKey; - hashCode = (hashCode * -1521134295) + link.targetKey; - return hashCode; - } - void logMessage(LogCategory category, LogLevel logLevel, String message) { return using((arena) { realmLib.realm_dart_log(logLevel.index, category.toString().toCharPtr(arena), message.toCharPtr(arena)); @@ -391,14 +369,6 @@ class _RealmCore { } } -class _RealmLinkHandle { - final int targetKey; - final int classKey; - _RealmLinkHandle(realm_link_t link) - : targetKey = link.target, - classKey = link.target_table; -} - class NotificationTokenHandle extends RootedHandleBase { NotificationTokenHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 32); } @@ -490,7 +460,7 @@ void _intoRealmValue(Object? value, realm_value realmValue, Allocator allocator) realmValue.type = realm_value_type.RLM_TYPE_NULL; } else if (value is RealmObjectBase) { // when converting a RealmObjectBase to realm_value.link we assume the object is managed - final link = realmCore._getObjectAsLink(value); + final link = value.handle.asLink; realmValue.values.link.target = link.targetKey; realmValue.values.link.target_table = link.classKey; realmValue.type = realm_value_type.RLM_TYPE_LINK; diff --git a/packages/realm_dart/lib/src/realm_class.dart b/packages/realm_dart/lib/src/realm_class.dart index 28e7c013c..fb784a4cb 100644 --- a/packages/realm_dart/lib/src/realm_class.dart +++ b/packages/realm_dart/lib/src/realm_class.dart @@ -518,7 +518,7 @@ class Realm implements Finalizable { bool operator ==(Object other) { if (identical(this, other)) return true; if (other is! Realm) return false; - return realmCore.realmEquals(this, other); + return handle == other.handle; } /// The logger that will emit log messages from the database and sync operations. diff --git a/packages/realm_dart/lib/src/realm_object.dart b/packages/realm_dart/lib/src/realm_object.dart index ae4f25272..99ce7797d 100644 --- a/packages/realm_dart/lib/src/realm_object.dart +++ b/packages/realm_dart/lib/src/realm_object.dart @@ -457,10 +457,10 @@ mixin RealmObjectBase on RealmEntity implements RealmObjectBaseMarker, Finalizab if (other is! RealmObjectBase) return false; if (!isManaged || !other.isManaged) return false; - return realmCore.objectEquals(this, other); + return handle == other.handle; } - late final int _managedHashCode = realmCore.objectGetHashCode(this); + late final int _managedHashCode = handle.hashCode; @override int get hashCode { diff --git a/packages/realm_dart/lib/src/user.dart b/packages/realm_dart/lib/src/user.dart index ea652b286..2c8e0d6a4 100644 --- a/packages/realm_dart/lib/src/user.dart +++ b/packages/realm_dart/lib/src/user.dart @@ -7,7 +7,6 @@ import 'dart:ffi'; import 'app.dart'; import 'credentials.dart'; -import 'native/realm_core.dart'; import 'native/user_handle.dart'; import 'realm_class.dart'; @@ -146,7 +145,7 @@ class User { bool operator ==(Object other) { if (identical(this, other)) return true; if (other is! User) return false; - return realmCore.userEquals(this, other); + return handle == other.handle; } void _ensureLoggedIn([String clarification = 'perform this action']) { From 6af1dd90de719172a0abf36ec5eb06df49abf1be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Fri, 3 May 2024 17:36:12 +0200 Subject: [PATCH 57/68] Move raiseIfNull to HandleBase ctor. Rename to be explicit about call to getLastError --- .../realm_dart/lib/src/native/app_handle.dart | 39 +++-- .../lib/src/native/config_handle.dart | 23 +-- .../lib/src/native/credentials_handle.dart | 4 +- .../lib/src/native/error_handling.dart | 17 ++- .../lib/src/native/handle_base.dart | 7 +- .../lib/src/native/list_handle.dart | 74 +++++---- .../realm_dart/lib/src/native/map_handle.dart | 81 +++++----- .../mutable_subscription_set_handle.dart | 12 +- .../lib/src/native/object_handle.dart | 60 ++++---- .../lib/src/native/query_handle.dart | 4 +- .../realm_dart/lib/src/native/realm_core.dart | 54 ++++--- .../lib/src/native/realm_handle.dart | 143 +++++++++--------- .../lib/src/native/results_handle.dart | 62 ++++---- .../lib/src/native/schema_handle.dart | 6 +- .../lib/src/native/session_handle.dart | 33 ++-- .../realm_dart/lib/src/native/set_handle.dart | 68 ++++----- .../src/native/subscription_set_handle.dart | 6 +- .../lib/src/native/user_handle.dart | 43 +++--- 18 files changed, 365 insertions(+), 371 deletions(-) diff --git a/packages/realm_dart/lib/src/native/app_handle.dart b/packages/realm_dart/lib/src/native/app_handle.dart index cac55fe55..364bb07d5 100644 --- a/packages/realm_dart/lib/src/native/app_handle.dart +++ b/packages/realm_dart/lib/src/native/app_handle.dart @@ -35,8 +35,7 @@ class AppHandle extends HandleBase { } final httpTransportHandle = _createHttpTransport(configuration.httpClient); final appConfigHandle = _createAppConfig(configuration, httpTransportHandle); - final appPtr = realmLib.realm_app_create_cached(appConfigHandle.pointer).raiseIfNull(); - return AppHandle(appPtr); + return AppHandle(realmLib.realm_app_create_cached(appConfigHandle.pointer)); } UserHandle? get currentUser { @@ -48,7 +47,7 @@ class AppHandle extends HandleBase { List _getUsers(Arena arena, {int expectedSize = 2}) { final actualCount = arena(); final usersPtr = arena>(expectedSize); - realmLib.realm_app_get_all_users(pointer, usersPtr, expectedSize, actualCount).raiseIfFalse(); + realmLib.realm_app_get_all_users(pointer, usersPtr, expectedSize, actualCount).raiseLastErrorIfFalse(); if (expectedSize < actualCount.value) { // The supplied array was too small - resize it @@ -74,7 +73,7 @@ class AppHandle extends HandleBase { createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseIfFalse("Remove user failed"); + .raiseLastErrorIfFalse("Remove user failed"); return completer.future; } @@ -85,7 +84,7 @@ class AppHandle extends HandleBase { pointer, user.pointer, ) - .raiseIfFalse("Switch user failed"); + .raiseLastErrorIfFalse("Switch user failed"); }); } @@ -107,7 +106,7 @@ class AppHandle extends HandleBase { createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseIfFalse("Update base URL failed"); + .raiseLastErrorIfFalse("Update base URL failed"); }); return completer.future; } @@ -122,7 +121,7 @@ class AppHandle extends HandleBase { createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseIfFalse("Refresh custom data failed"); + .raiseLastErrorIfFalse("Refresh custom data failed"); return completer.future; } @@ -140,7 +139,7 @@ class AppHandle extends HandleBase { createAsyncUserCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseIfFalse("Login failed"); + .raiseLastErrorIfFalse("Login failed"); return await completer.future; } @@ -156,7 +155,7 @@ class AppHandle extends HandleBase { createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); }); return completer.future; } @@ -173,7 +172,7 @@ class AppHandle extends HandleBase { createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); }); return await completer.future; } @@ -189,7 +188,7 @@ class AppHandle extends HandleBase { createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); }); return completer.future; } @@ -207,7 +206,7 @@ class AppHandle extends HandleBase { createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); }); return completer.future; } @@ -223,7 +222,7 @@ class AppHandle extends HandleBase { createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); }); return completer.future; } @@ -241,7 +240,7 @@ class AppHandle extends HandleBase { createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); }); return completer.future; } @@ -257,7 +256,7 @@ class AppHandle extends HandleBase { createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); }); return completer.future; } @@ -272,7 +271,7 @@ class AppHandle extends HandleBase { createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseIfFalse("Logout failed"); + .raiseLastErrorIfFalse("Logout failed"); } else { realmLib .realm_app_log_out( @@ -282,7 +281,7 @@ class AppHandle extends HandleBase { createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseIfFalse("Logout failed"); + .raiseLastErrorIfFalse("Logout failed"); } return completer.future; } @@ -297,7 +296,7 @@ class AppHandle extends HandleBase { createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseIfFalse("Delete user failed"); + .raiseLastErrorIfFalse("Delete user failed"); return completer.future; } @@ -310,7 +309,7 @@ class AppHandle extends HandleBase { realmPath.toCharPtr(arena), didRun, ) - .raiseIfFalse("An error occurred while resetting the Realm. Check if the file is in use: '$realmPath'"); + .raiseLastErrorIfFalse("An error occurred while resetting the Realm. Check if the file is in use: '$realmPath'"); return didRun.value; }); } @@ -329,7 +328,7 @@ class AppHandle extends HandleBase { createAsyncFunctionCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); return completer.future; }); } diff --git a/packages/realm_dart/lib/src/native/config_handle.dart b/packages/realm_dart/lib/src/native/config_handle.dart index 27fd40d51..405e2c0f5 100644 --- a/packages/realm_dart/lib/src/native/config_handle.dart +++ b/packages/realm_dart/lib/src/native/config_handle.dart @@ -4,13 +4,13 @@ import 'dart:ffi'; import 'package:ffi/ffi.dart'; +import 'package:realm_dart/src/native/error_handling.dart'; import '../configuration.dart'; // TODO: Remove this import import '../migration.dart'; // TODO: Remove this import import '../realm_class.dart'; // TODO: Remove this import import '../scheduler.dart'; // TODO: Remove this import import '../user.dart'; // TODO: Remove this import -import 'error_handling.dart'; import 'handle_base.dart'; import 'realm_bindings.dart'; import 'realm_core.dart'; @@ -22,9 +22,8 @@ class ConfigHandle extends HandleBase { ConfigHandle(Pointer pointer) : super(pointer, 512); factory ConfigHandle.from(Configuration config) { - return using((Arena arena) { - final configPtr = realmLib.realm_config_new(); - final configHandle = ConfigHandle(configPtr); + return using((arena) { + final configHandle = ConfigHandle(realmLib.realm_config_new()); if (config.schemaObjects.isNotEmpty) { final schemaHandle = SchemaHandle.from(config.schemaObjects); @@ -88,7 +87,7 @@ class ConfigHandle extends HandleBase { realmLib.realm_config_set_in_memory(configHandle.pointer, true); } else if (config is FlexibleSyncConfiguration) { realmLib.realm_config_set_schema_mode(configHandle.pointer, realm_schema_mode.RLM_SCHEMA_MODE_ADDITIVE_DISCOVERED); - final syncConfigPtr = realmLib.realm_flx_sync_config_new(config.user.handle.pointer).raiseIfNull(); + final syncConfigPtr = realmLib.realm_flx_sync_config_new(config.user.handle.pointer)..raiseLastErrorIfNull(); try { realmLib.realm_sync_config_set_session_stop_policy(syncConfigPtr, config.sessionStopPolicy.index); realmLib.realm_sync_config_set_resync_mode(syncConfigPtr, config.clientResetHandler.clientResyncMode.index); @@ -125,17 +124,17 @@ class ConfigHandle extends HandleBase { ); } - realmLib.realm_config_set_sync_config(configPtr, syncConfigPtr); + realmLib.realm_config_set_sync_config(configHandle.pointer, syncConfigPtr); } finally { realmLib.realm_release(syncConfigPtr.cast()); } } else if (config is DisconnectedSyncConfiguration) { realmLib.realm_config_set_schema_mode(configHandle.pointer, realm_schema_mode.RLM_SCHEMA_MODE_ADDITIVE_EXPLICIT); - realmLib.realm_config_set_force_sync_history(configPtr, true); + realmLib.realm_config_set_force_sync_history(configHandle.pointer, true); } if (config.encryptionKey != null) { - realmLib.realm_config_set_encryption_key(configPtr, config.encryptionKey!.toUint8Ptr(arena), encryptionKeySize); + realmLib.realm_config_set_encryption_key(configHandle.pointer, config.encryptionKey!.toUint8Ptr(arena), encryptionKeySize); } // For sync and for dynamic Realms, we need to have a complete view of the schema in Core. @@ -159,8 +158,12 @@ void _syncAfterResetCallback(Object userdata, Pointer beforeHandle } final beforeRealm = RealmInternal.getUnowned(syncConfig, RealmHandle.unowned(beforeHandle)); - final realmPtr = realmLib.realm_from_thread_safe_reference(afterReference, scheduler.handle.pointer).raiseIfNull(); - final afterRealm = RealmInternal.getUnowned(syncConfig, RealmHandle.unowned(realmPtr)); + final afterRealm = RealmInternal.getUnowned( + syncConfig, + RealmHandle.unowned(realmLib.realm_from_thread_safe_reference( + afterReference, + scheduler.handle.pointer, + ))); try { return await afterResetCallback(beforeRealm, afterRealm); diff --git a/packages/realm_dart/lib/src/native/credentials_handle.dart b/packages/realm_dart/lib/src/native/credentials_handle.dart index 78a86b557..5f7f1811b 100644 --- a/packages/realm_dart/lib/src/native/credentials_handle.dart +++ b/packages/realm_dart/lib/src/native/credentials_handle.dart @@ -6,7 +6,6 @@ import 'dart:ffi'; import 'package:ffi/ffi.dart'; import '../credentials.dart'; // TODO: Remove this import -import 'error_handling.dart'; import 'handle_base.dart'; import 'realm_bindings.dart'; import 'realm_core.dart'; // TODO: Remove this import @@ -65,8 +64,7 @@ class CredentialsHandle extends HandleBase { factory CredentialsHandle.function(String payload) { return using((arena) { final payloadPtr = payload.toCharPtr(arena); - final credentialsPtr = realmLib.realm_app_credentials_new_function(payloadPtr).raiseIfNull(); - return CredentialsHandle(credentialsPtr); + return CredentialsHandle(realmLib.realm_app_credentials_new_function(payloadPtr)); }); } diff --git a/packages/realm_dart/lib/src/native/error_handling.dart b/packages/realm_dart/lib/src/native/error_handling.dart index 10bda93a7..ae8e079ea 100644 --- a/packages/realm_dart/lib/src/native/error_handling.dart +++ b/packages/realm_dart/lib/src/native/error_handling.dart @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import 'dart:ffi'; +import 'dart:io'; import 'package:ffi/ffi.dart'; @@ -11,13 +12,17 @@ import 'realm_core.dart'; import 'realm_library.dart'; extension PointerEx on Pointer { - Pointer raiseIfNull([String? message]) => this == nullptr ? throwLastError(message) : this; + void raiseLastErrorIfNull([String? message]) { + if (this == nullptr) { + raiseLastError(message); + } + } } extension BoolEx on bool { - void raiseIfFalse([String? message]) { + void raiseLastErrorIfFalse([String? message]) { if (!this) { - throwLastError(message); + raiseLastError(message); } } } @@ -39,9 +44,11 @@ LastError? getLastError(Allocator allocator) { return success ? error.ref.toDart() : null; } -Never throwLastError([String? errorMessage]) { - using((Arena arena) { +Never raiseLastError([String? errorMessage]) { + using((arena) { final lastError = getLastError(arena); + //raise(lastError); + if (lastError?.userError != null) { throw UserCallbackException(lastError!.userError!); } diff --git a/packages/realm_dart/lib/src/native/handle_base.dart b/packages/realm_dart/lib/src/native/handle_base.dart index e15b0d78a..f4a3cbfe5 100644 --- a/packages/realm_dart/lib/src/native/handle_base.dart +++ b/packages/realm_dart/lib/src/native/handle_base.dart @@ -3,6 +3,8 @@ import 'dart:ffi'; +import 'package:realm_dart/src/native/error_handling.dart'; + import 'realm_library.dart'; // Flag to enable trace on finalization. @@ -41,6 +43,7 @@ abstract class HandleBase implements Finalizable { void keepAlive() {} HandleBase(this.pointer, int size) : isUnowned = false { + pointer.raiseLastErrorIfNull(); _finalizableHandle = realmLib.realm_attach_finalizer(this, pointer.cast(), size); if (_enableFinalizerTrace) { @@ -48,7 +51,9 @@ abstract class HandleBase implements Finalizable { } } - HandleBase.unowned(this.pointer) : isUnowned = true; + HandleBase.unowned(this.pointer) : isUnowned = true { + pointer.raiseLastErrorIfNull(); + } @override String toString() => "${pointer.toString()} value=${pointer.cast().value}${isUnowned ? ' (unowned)' : ''}"; diff --git a/packages/realm_dart/lib/src/native/list_handle.dart b/packages/realm_dart/lib/src/native/list_handle.dart index 24bdc7db3..1fa5b7161 100644 --- a/packages/realm_dart/lib/src/native/list_handle.dart +++ b/packages/realm_dart/lib/src/native/list_handle.dart @@ -22,32 +22,31 @@ class ListHandle extends CollectionHandleBase { bool get isValid => realmLib.realm_list_is_valid(pointer); ResultsHandle asResults() { - final ptr = realmLib.realm_list_to_results(pointer).raiseIfNull(); - return ResultsHandle(ptr, root); + return ResultsHandle(realmLib.realm_list_to_results(pointer), root); } int get size { - return using((Arena arena) { + return using((arena) { final size = arena(); - realmLib.realm_list_size(pointer, size).raiseIfFalse(); + realmLib.realm_list_size(pointer, size).raiseLastErrorIfFalse(); return size.value; }); } void removeAt(int index) { - realmLib.realm_list_erase(pointer, index).raiseIfFalse(); + realmLib.realm_list_erase(pointer, index).raiseLastErrorIfFalse(); } void move(int from, int to) { - realmLib.realm_list_move(pointer, from, to).raiseIfFalse(); + realmLib.realm_list_move(pointer, from, to).raiseLastErrorIfFalse(); } void deleteAll() { - realmLib.realm_list_remove_all(pointer).raiseIfFalse(); + realmLib.realm_list_remove_all(pointer).raiseLastErrorIfFalse(); } int indexOf(Object? value) { - return using((Arena arena) { + return using((arena) { final outIndex = arena(); final outFound = arena(); @@ -60,20 +59,20 @@ class ListHandle extends CollectionHandleBase { outIndex, outFound, ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); return outFound.value ? outIndex.value : -1; }); } void clear() { - realmLib.realm_list_clear(pointer).raiseIfFalse(); + realmLib.realm_list_clear(pointer).raiseLastErrorIfFalse(); } // TODO: avoid taking the [realm] parameter Object? elementAt(Realm realm, int index) { - return using((Arena arena) { + return using((arena) { final realmValue = arena(); - realmLib.realm_list_get(pointer, index, realmValue).raiseIfFalse(); + realmLib.realm_list_get(pointer, index, realmValue).raiseLastErrorIfFalse(); return realmValue.toDartValue( realm, () => realmLib.realm_list_get_list(pointer, index), @@ -83,18 +82,18 @@ class ListHandle extends CollectionHandleBase { } ListHandle? resolveIn(RealmHandle frozenRealm) { - return using((Arena arena) { + return using((arena) { final resultPtr = arena>(); - realmLib.realm_list_resolve_in(pointer, frozenRealm.pointer, resultPtr).raiseIfFalse(); + realmLib.realm_list_resolve_in(pointer, frozenRealm.pointer, resultPtr).raiseLastErrorIfFalse(); return resultPtr == nullptr ? null : ListHandle(resultPtr.value, root); }); } // TODO: Consider splitting into two methods void addOrUpdateAt(int index, Object? value, bool insert) { - using((Arena arena) { + using((arena) { final realmValue = value.toNative(arena); - (insert ? realmLib.realm_list_insert : realmLib.realm_list_set)(pointer, index, realmValue.ref).raiseIfFalse(); + (insert ? realmLib.realm_list_insert : realmLib.realm_list_set)(pointer, index, realmValue.ref).raiseLastErrorIfFalse(); }); } @@ -105,13 +104,11 @@ class ListHandle extends CollectionHandleBase { } ObjectHandle setEmbeddedAt(int index) { - final ptr = realmLib.realm_list_set_embedded(pointer, index).raiseIfNull(); - return ObjectHandle(ptr, root); + return ObjectHandle(realmLib.realm_list_set_embedded(pointer, index), root); } ObjectHandle insertEmbeddedAt(int index) { - final ptr = realmLib.realm_list_insert_embedded(pointer, index).raiseIfNull(); - return ObjectHandle(ptr, root); + return ObjectHandle(realmLib.realm_list_insert_embedded(pointer, index), root); } ResultsHandle query(String query, List args) { @@ -122,29 +119,28 @@ class ListHandle extends CollectionHandleBase { intoRealmQueryArg(args[i], argsPointer + i, arena); } final queryHandle = QueryHandle( - realmLib - .realm_query_parse_for_list( - pointer, - query.toCharPtr(arena), - length, - argsPointer, - ) - .raiseIfNull(), - root); + realmLib.realm_query_parse_for_list( + pointer, + query.toCharPtr(arena), + length, + argsPointer, + ), + root, + ); return queryHandle.findAll(); }); } NotificationTokenHandle subscribeForNotifications(NotificationsController controller) { - final ptr = realmLib - .realm_list_add_notification_callback( - pointer, - controller.toPersistentHandle(), - realmLib.addresses.realm_dart_delete_persistent_handle, - nullptr, - Pointer.fromFunction(collectionChangeCallback), - ) - .raiseIfNull(); - return NotificationTokenHandle(ptr, root); + return NotificationTokenHandle( + realmLib.realm_list_add_notification_callback( + pointer, + controller.toPersistentHandle(), + realmLib.addresses.realm_dart_delete_persistent_handle, + nullptr, + Pointer.fromFunction(collectionChangeCallback), + ), + root, + ); } } diff --git a/packages/realm_dart/lib/src/native/map_handle.dart b/packages/realm_dart/lib/src/native/map_handle.dart index e7e3f4dda..f23f502d2 100644 --- a/packages/realm_dart/lib/src/native/map_handle.dart +++ b/packages/realm_dart/lib/src/native/map_handle.dart @@ -21,29 +21,29 @@ class MapHandle extends CollectionHandleBase { MapHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 96); // TODO: check size int get size { - return using((Arena arena) { + return using((arena) { final outSize = arena(); - realmLib.realm_dictionary_size(pointer, outSize).raiseIfFalse(); + realmLib.realm_dictionary_size(pointer, outSize).raiseLastErrorIfFalse(); return outSize.value; }); } bool remove(String key) { - return using((Arena arena) { + return using((arena) { final keyNative = key.toNative(arena); final outErased = arena(); - realmLib.realm_dictionary_erase(pointer, keyNative.ref, outErased).raiseIfFalse(); + realmLib.realm_dictionary_erase(pointer, keyNative.ref, outErased).raiseLastErrorIfFalse(); return outErased.value; }); } // TODO: avoid taking the [realm] parameter Object? find(Realm realm, String key) { - return using((Arena arena) { + return using((arena) { final keyNative = key.toNative(arena); final outValue = arena(); final outFound = arena(); - realmLib.realm_dictionary_find(pointer, keyNative.ref, outValue, outFound).raiseIfFalse(); + realmLib.realm_dictionary_find(pointer, keyNative.ref, outValue, outFound).raiseLastErrorIfFalse(); if (outFound.value) { return outValue.toDartValue( realm, @@ -60,38 +60,37 @@ class MapHandle extends CollectionHandleBase { } void clear() { - realmLib.realm_dictionary_clear(pointer).raiseIfFalse(); + realmLib.realm_dictionary_clear(pointer).raiseLastErrorIfFalse(); } ResultsHandle get keys { - return using((Arena arena) { + return using((arena) { final outSize = arena(); final outKeys = arena>(); - realmLib.realm_dictionary_get_keys(pointer, outSize, outKeys).raiseIfFalse(); + realmLib.realm_dictionary_get_keys(pointer, outSize, outKeys).raiseLastErrorIfFalse(); return ResultsHandle(outKeys.value, root); }); } ResultsHandle get values { - final ptr = realmLib.realm_dictionary_to_results(pointer).raiseIfNull(); - return ResultsHandle(ptr, root); + return ResultsHandle(realmLib.realm_dictionary_to_results(pointer), root); } bool containsKey(String key) { - return using((Arena arena) { + return using((arena) { final keyNative = key.toNative(arena); final found = arena(); - realmLib.realm_dictionary_contains_key(pointer, keyNative.ref, found).raiseIfFalse(); + realmLib.realm_dictionary_contains_key(pointer, keyNative.ref, found).raiseLastErrorIfFalse(); return found.value; }); } int indexOf(Object? value) { - return using((Arena arena) { + return using((arena) { // TODO: how should this behave for collections final valueNative = value.toNative(arena); final index = arena(); - realmLib.realm_dictionary_contains_value(pointer, valueNative.ref, index).raiseIfFalse(); + realmLib.realm_dictionary_contains_value(pointer, valueNative.ref, index).raiseLastErrorIfFalse(); return index.value; }); } @@ -99,15 +98,14 @@ class MapHandle extends CollectionHandleBase { bool containsValue(Object? value) => indexOf(value) > -1; ObjectHandle insertEmbedded(String key) { - return using((Arena arena) { + return using((arena) { final keyNative = key.toNative(arena); - final ptr = realmLib.realm_dictionary_insert_embedded(pointer, keyNative.ref).raiseIfNull(); - return ObjectHandle(ptr, root); + return ObjectHandle(realmLib.realm_dictionary_insert_embedded(pointer, keyNative.ref), root); }); } void insert(String key, Object? value) { - using((Arena arena) { + using((arena) { final keyNative = key.toNative(arena); final valueNative = value.toNative(arena); realmLib @@ -118,12 +116,12 @@ class MapHandle extends CollectionHandleBase { nullptr, nullptr, ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); }); } void insertCollection(Realm realm, String key, RealmValue value) { - using((Arena arena) { + using((arena) { final keyNative = key.toNative(arena); createCollection( realm, @@ -143,38 +141,37 @@ class MapHandle extends CollectionHandleBase { } final queryHandle = QueryHandle( - realmLib - .realm_query_parse_for_results( - values.pointer, - query.toCharPtr(arena), - length, - argsPointer, - ) - .raiseIfNull(), - root); + realmLib.realm_query_parse_for_results( + values.pointer, + query.toCharPtr(arena), + length, + argsPointer, + ), + root, + ); return queryHandle.findAll(); }); } MapHandle? resolveIn(RealmHandle frozenRealm) { - return using((Arena arena) { + return using((arena) { final resultPtr = arena>(); - realmLib.realm_dictionary_resolve_in(pointer, frozenRealm.pointer, resultPtr).raiseIfFalse(); + realmLib.realm_dictionary_resolve_in(pointer, frozenRealm.pointer, resultPtr).raiseLastErrorIfFalse(); return resultPtr == nullptr ? null : MapHandle(resultPtr.value, root); }); } NotificationTokenHandle subscribeForNotifications(NotificationsController controller) { - final ptr = realmLib - .realm_dictionary_add_notification_callback( - pointer, - controller.toPersistentHandle(), - realmLib.addresses.realm_dart_delete_persistent_handle, - nullptr, - Pointer.fromFunction(_mapChangeCallback), - ) - .raiseIfNull(); - return NotificationTokenHandle(ptr, root); + return NotificationTokenHandle( + realmLib.realm_dictionary_add_notification_callback( + pointer, + controller.toPersistentHandle(), + realmLib.addresses.realm_dart_delete_persistent_handle, + nullptr, + Pointer.fromFunction(_mapChangeCallback), + ), + root, + ); } } diff --git a/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart b/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart index 0965966e6..f48b1288c 100644 --- a/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart +++ b/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart @@ -20,7 +20,7 @@ class MutableSubscriptionSetHandle extends SubscriptionSetHandle { Pointer get _mutablePointer => super.pointer.cast(); - SubscriptionSetHandle commit() => SubscriptionSetHandle(realmLib.realm_sync_subscription_set_commit(_mutablePointer).raiseIfNull(), root); + SubscriptionSetHandle commit() => SubscriptionSetHandle(realmLib.realm_sync_subscription_set_commit(_mutablePointer), root); SubscriptionHandle insertOrAssignSubscription(ResultsHandle results, String? name, bool update) { if (!update) { @@ -39,7 +39,7 @@ class MutableSubscriptionSetHandle extends SubscriptionSetHandle { outIndex, outInserted, ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); return this[outIndex.value]; }); } @@ -53,7 +53,7 @@ class MutableSubscriptionSetHandle extends SubscriptionSetHandle { subscription.id.toNative(arena), outErased, ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); return outErased.value; }); } @@ -67,7 +67,7 @@ class MutableSubscriptionSetHandle extends SubscriptionSetHandle { name.toCharPtr(arena), outErased, ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); return outErased.value; }); } @@ -81,10 +81,10 @@ class MutableSubscriptionSetHandle extends SubscriptionSetHandle { results.pointer, outErased, ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); return outErased.value; }); } - void clear() => realmLib.realm_sync_subscription_set_clear(_mutablePointer).raiseIfFalse(); + void clear() => realmLib.realm_sync_subscription_set_clear(_mutablePointer).raiseLastErrorIfFalse(); } diff --git a/packages/realm_dart/lib/src/native/object_handle.dart b/packages/realm_dart/lib/src/native/object_handle.dart index 42aae6935..979e09718 100644 --- a/packages/realm_dart/lib/src/native/object_handle.dart +++ b/packages/realm_dart/lib/src/native/object_handle.dart @@ -22,15 +22,14 @@ class ObjectHandle extends RootedHandleBase { ObjectHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 112); ObjectHandle createEmbedded(int propertyKey) { - final objectPtr = realmLib.realm_set_embedded(pointer, propertyKey).raiseIfNull(); - return ObjectHandle(objectPtr, root); + return ObjectHandle(realmLib.realm_set_embedded(pointer, propertyKey), root); } (ObjectHandle, int) get parent { - return using((Arena arena) { + return using((arena) { final parentPtr = arena>(); final classKeyPtr = arena(); - realmLib.realm_object_get_parent(pointer, parentPtr, classKeyPtr).raiseIfFalse(); + realmLib.realm_object_get_parent(pointer, parentPtr, classKeyPtr).raiseLastErrorIfFalse(); final handle = ObjectHandle(parentPtr.value, root); @@ -49,9 +48,9 @@ class ObjectHandle extends RootedHandleBase { // TODO: avoid taking the [realm] parameter Object? getValue(Realm realm, int propertyKey) { - return using((Arena arena) { + return using((arena) { final realmValue = arena(); - realmLib.realm_get_value(pointer, propertyKey, realmValue).raiseIfFalse(); + realmLib.realm_get_value(pointer, propertyKey, realmValue).raiseLastErrorIfFalse(); return realmValue.toDartValue( realm, () => realmLib.realm_get_list(pointer, propertyKey), @@ -63,7 +62,7 @@ class ObjectHandle extends RootedHandleBase { // TODO: value should be RealmValue, and perhaps this method should be combined // with setCollection? void setValue(int propertyKey, Object? value, bool isDefault) { - using((Arena arena) { + using((arena) { final realmValue = value.toNative(arena); realmLib .realm_set_value( @@ -72,28 +71,24 @@ class ObjectHandle extends RootedHandleBase { realmValue.ref, isDefault, ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); }); } ListHandle getList(int propertyKey) { - final ptr = realmLib.realm_get_list(pointer, propertyKey).raiseIfNull(); - return ListHandle(ptr, root); + return ListHandle(realmLib.realm_get_list(pointer, propertyKey), root); } SetHandle getSet(int propertyKey) { - final ptr = realmLib.realm_get_set(pointer, propertyKey).raiseIfNull(); - return SetHandle(ptr, root); + return SetHandle(realmLib.realm_get_set(pointer, propertyKey), root); } MapHandle getMap(int propertyKey) { - final ptr = realmLib.realm_get_dictionary(pointer, propertyKey).raiseIfNull(); - return MapHandle(ptr, root); + return MapHandle(realmLib.realm_get_dictionary(pointer, propertyKey), root); } ResultsHandle getBacklinks(int sourceTableKey, int propertyKey) { - final ptr = realmLib.realm_get_backlinks(pointer, sourceTableKey, propertyKey).raiseIfNull(); - return ResultsHandle(ptr, root); + return ResultsHandle(realmLib.realm_get_backlinks(pointer, sourceTableKey, propertyKey), root); } void setCollection(Realm realm, int propertyKey, RealmValue value) { @@ -110,36 +105,35 @@ class ObjectHandle extends RootedHandleBase { } void delete() { - realmLib.realm_object_delete(pointer).raiseIfFalse(); + realmLib.realm_object_delete(pointer).raiseLastErrorIfFalse(); } ObjectHandle? resolveIn(RealmHandle frozenRealm) { - return using((Arena arena) { + return using((arena) { final resultPtr = arena>(); - realmLib.realm_object_resolve_in(pointer, frozenRealm.pointer, resultPtr).raiseIfFalse(); + realmLib.realm_object_resolve_in(pointer, frozenRealm.pointer, resultPtr).raiseLastErrorIfFalse(); return resultPtr == nullptr ? null : ObjectHandle(resultPtr.value, frozenRealm); }); } NotificationTokenHandle subscribeForNotifications(NotificationsController controller, [List? keyPaths]) { - return using((Arena arena) { + return using((arena) { final kpNative = buildAndVerifyKeyPath(keyPaths); - final ptr = realmLib - .realm_object_add_notification_callback( - pointer, - controller.toPersistentHandle(), - realmLib.addresses.realm_dart_delete_persistent_handle, - kpNative, - Pointer.fromFunction(_objectChangeCallback), - ) - .raiseIfNull(); - - return NotificationTokenHandle(ptr, root); + return NotificationTokenHandle( + realmLib.realm_object_add_notification_callback( + pointer, + controller.toPersistentHandle(), + realmLib.addresses.realm_dart_delete_persistent_handle, + kpNative, + Pointer.fromFunction(_objectChangeCallback), + ), + root, + ); }); } Pointer buildAndVerifyKeyPath(List? keyPaths) { - return using((Arena arena) { + return using((arena) { if (keyPaths == null) { return nullptr; } @@ -152,7 +146,7 @@ class ObjectHandle extends RootedHandleBase { } // TODO(kn): // call to classKey getter involves a native call, which is not ideal - return realmLib.realm_create_key_path_array(root.pointer, classKey, length, keypathsNative).raiseIfNull(); + return realmLib.realm_create_key_path_array(root.pointer, classKey, length, keypathsNative)..raiseLastErrorIfNull(); }); } diff --git a/packages/realm_dart/lib/src/native/query_handle.dart b/packages/realm_dart/lib/src/native/query_handle.dart index 19fe6f59d..88a2e1856 100644 --- a/packages/realm_dart/lib/src/native/query_handle.dart +++ b/packages/realm_dart/lib/src/native/query_handle.dart @@ -3,7 +3,6 @@ import 'dart:ffi'; -import 'error_handling.dart'; import 'realm_bindings.dart'; import 'realm_handle.dart'; import 'realm_library.dart'; @@ -15,8 +14,7 @@ class QueryHandle extends RootedHandleBase { ResultsHandle findAll() { try { - final resultsPointer = realmLib.realm_query_find_all(pointer).raiseIfNull(); - return ResultsHandle(resultsPointer, root); + return ResultsHandle(realmLib.realm_query_find_all(pointer), root); } finally { release(); } diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 7ca5ba3c8..3fc1a6fd2 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -132,8 +132,7 @@ void createCollection(Realm realm, RealmValue value, Pointer Functio try { switch (value.collectionType) { case RealmCollectionType.list: - final listPointer = createList().raiseIfNull(); - final listHandle = ListHandle(listPointer, realm.handle); + final listHandle = ListHandle(createList(), realm.handle); collectionHandle = listHandle; final list = realm.createList(listHandle, null); @@ -145,8 +144,7 @@ void createCollection(Realm realm, RealmValue value, Pointer Functio list.add(item); } case RealmCollectionType.map: - final mapPointer = createMap().raiseIfNull(); - final mapHandle = MapHandle(mapPointer, realm.handle); + final mapHandle = MapHandle(createMap(), realm.handle); collectionHandle = mapHandle; final map = realm.createMap(mapHandle, null); @@ -222,7 +220,7 @@ class _RealmCore { AsyncOpenTaskHandle createRealmAsyncOpenTask(FlexibleSyncConfiguration config) { final configHandle = ConfigHandle.from(config); - final asyncOpenTaskPtr = realmLib.realm_open_synchronized(configHandle.pointer).raiseIfNull("Error opening realm at path ${config.path}"); + final asyncOpenTaskPtr = realmLib.realm_open_synchronized(configHandle.pointer)..raiseLastErrorIfNull("Error opening realm at path ${config.path}"); return AsyncOpenTaskHandle(asyncOpenTaskPtr); } @@ -243,7 +241,7 @@ class _RealmCore { } static void openRealmAsyncCallback(Object userData, Pointer realmSafePtr, Pointer error) { - return using((Arena arena) { + return using((arena) { final completer = userData as CancellableCompleter; if (completer.isCancelled) { return; @@ -255,8 +253,7 @@ class _RealmCore { return; } - final realmPtr = realmLib.realm_from_thread_safe_reference(realmSafePtr, scheduler.handle.pointer).raiseIfNull(); - completer.complete(RealmHandle(realmPtr)); + completer.complete(RealmHandle(realmLib.realm_from_thread_safe_reference(realmSafePtr, scheduler.handle.pointer))); }); } @@ -265,24 +262,25 @@ class _RealmCore { } AsyncOpenTaskProgressNotificationTokenHandle realmAsyncOpenRegisterAsyncOpenProgressNotifier( - AsyncOpenTaskHandle handle, RealmAsyncOpenProgressNotificationsController controller) { + AsyncOpenTaskHandle handle, + RealmAsyncOpenProgressNotificationsController controller, + ) { final callback = Pointer.fromFunction(syncProgressCallback); final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); - final tokenPtr = realmLib - .realm_async_open_task_register_download_progress_notifier( - handle.pointer, - realmLib.addresses.realm_dart_sync_progress_callback, - userdata.cast(), - realmLib.addresses.realm_dart_userdata_async_free, - ) - .raiseIfNull(); - return AsyncOpenTaskProgressNotificationTokenHandle(tokenPtr); + return AsyncOpenTaskProgressNotificationTokenHandle( + realmLib.realm_async_open_task_register_download_progress_notifier( + handle.pointer, + realmLib.addresses.realm_dart_sync_progress_callback, + userdata.cast(), + realmLib.addresses.realm_dart_userdata_async_free, + ), + ); } void deleteRealmFiles(String path) { - using((Arena arena) { + using((arena) { final realmDeleted = arena(); - realmLib.realm_delete_files(path.toCharPtr(arena), realmDeleted).raiseIfFalse("Error deleting realm at path $path"); + realmLib.realm_delete_files(path.toCharPtr(arena), realmDeleted).raiseLastErrorIfFalse("Error deleting realm at path $path"); }); } @@ -303,7 +301,7 @@ class _RealmCore { AppHandle? getApp(String id, String? baseUrl) { return using((arena) { final outApp = arena>(); - realmLib.realm_app_get_cached(id.toCharPtr(arena), baseUrl == null ? nullptr : baseUrl.toCharPtr(arena), outApp).raiseIfFalse(); + realmLib.realm_app_get_cached(id.toCharPtr(arena), baseUrl == null ? nullptr : baseUrl.toCharPtr(arena), outApp).raiseLastErrorIfFalse(); return outApp.value == nullptr ? null : AppHandle(outApp.value); }); } @@ -589,16 +587,14 @@ extension RealmValueEx on realm_value_t { throw RealmException('toDartValue called with a list argument but without a list getter'); } - final listPointer = getList().raiseIfNull(); - final listHandle = ListHandle(listPointer, realm.handle); + final listHandle = ListHandle(getList(), realm.handle); return realm.createList(listHandle, null); case realm_value_type.RLM_TYPE_DICTIONARY: if (getMap == null || realm == null) { throw RealmException('toDartValue called with a list argument but without a list getter'); } - final mapPointer = getMap().raiseIfNull(); - final mapHandle = MapHandle(mapPointer, realm.handle); + final mapHandle = MapHandle(getMap(), realm.handle); return realm.createMap(mapHandle, null); default: throw RealmException("realm_value_type $type not supported"); @@ -757,6 +753,14 @@ extension RealmPropertyInfoEx on realm_property_info { } extension CompleterEx on Completer { + void completeFrom(FutureOr Function() action) { + try { + complete(action()); + } catch (error, stackTrace) { + completeError(error, stackTrace); + } + } + void completeWithAppError(Pointer error) { final message = error.ref.message.cast().toRealmDartString()!; final linkToLogs = error.ref.link_to_server_logs.cast().toRealmDartString(); diff --git a/packages/realm_dart/lib/src/native/realm_handle.dart b/packages/realm_dart/lib/src/native/realm_handle.dart index 55d2b4a09..1e7e0bd9f 100644 --- a/packages/realm_dart/lib/src/native/realm_handle.dart +++ b/packages/realm_dart/lib/src/native/realm_handle.dart @@ -36,8 +36,8 @@ class RealmHandle extends HandleBase { factory RealmHandle.open(Configuration config) { final configHandle = ConfigHandle.from(config); - final realmPtr = realmLib.realm_open(configHandle.pointer).raiseIfNull('Error opening realm at path ${config.path}'); - return RealmHandle(realmPtr); + return RealmHandle(realmLib.realm_open(configHandle.pointer) // + ..raiseLastErrorIfNull('Error opening realm at path ${config.path}')); } int addChild(RootedHandleBase child) { @@ -65,45 +65,43 @@ class RealmHandle extends HandleBase { } ObjectHandle createWithPrimaryKey(int classKey, Object? primaryKey) { - return using((Arena arena) { + return using((arena) { final realmValue = primaryKey.toNative(arena); - final realmPtr = realmLib.realm_object_create_with_primary_key(pointer, classKey, realmValue.ref).raiseIfNull(); - return ObjectHandle(realmPtr, this); + return ObjectHandle(realmLib.realm_object_create_with_primary_key(pointer, classKey, realmValue.ref), this); }); } ObjectHandle create(int classKey) { - final realmPtr = realmLib.realm_object_create(pointer, classKey).raiseIfNull(); - return ObjectHandle(realmPtr, this); + return ObjectHandle(realmLib.realm_object_create(pointer, classKey), this); } ObjectHandle getOrCreateWithPrimaryKey(int classKey, Object? primaryKey) { - return using((Arena arena) { + return using((arena) { final realmValue = primaryKey.toNative(arena); final didCreate = arena(); - final realmPtr = realmLib - .realm_object_get_or_create_with_primary_key( - pointer, - classKey, - realmValue.ref, - didCreate, - ) - .raiseIfNull(); - return ObjectHandle(realmPtr, this); + return ObjectHandle( + realmLib.realm_object_get_or_create_with_primary_key( + pointer, + classKey, + realmValue.ref, + didCreate, + ), + this, + ); }); } bool compact() { return using((arena) { final outDidCompact = arena(); - realmLib.realm_compact(pointer, outDidCompact).raiseIfFalse(); + realmLib.realm_compact(pointer, outDidCompact).raiseLastErrorIfFalse(); return outDidCompact.value; }); } void writeCopy(Configuration config) { final configHandle = ConfigHandle.from(config); - realmLib.realm_convert_with_config(pointer, configHandle.pointer, false).raiseIfFalse(); + realmLib.realm_convert_with_config(pointer, configHandle.pointer, false).raiseLastErrorIfFalse(); } ResultsHandle queryClass(int classKey, String query, List args) { @@ -114,24 +112,23 @@ class RealmHandle extends HandleBase { intoRealmQueryArg(args[i], argsPointer + i, arena); } final queryHandle = QueryHandle( - realmLib - .realm_query_parse( - pointer, - classKey, - query.toCharPtr(arena), - length, - argsPointer, - ) - .raiseIfNull(), - this); + realmLib.realm_query_parse( + pointer, + classKey, + query.toCharPtr(arena), + length, + argsPointer, + ), + this, + ); return queryHandle.findAll(); }); } - RealmHandle freeze() => RealmHandle(realmLib.realm_freeze(pointer).raiseIfNull()); + RealmHandle freeze() => RealmHandle(realmLib.realm_freeze(pointer)); SessionHandle getSession() { - return SessionHandle(realmLib.realm_sync_session_get(pointer).raiseIfNull(), this); + return SessionHandle(realmLib.realm_sync_session_get(pointer), this); } bool get isFrozen { @@ -139,7 +136,7 @@ class RealmHandle extends HandleBase { } SubscriptionSetHandle get subscriptions { - return SubscriptionSetHandle(realmLib.realm_sync_get_active_subscription_set(pointer).raiseIfNull(), this); + return SubscriptionSetHandle(realmLib.realm_sync_get_active_subscription_set(pointer), this); } void disableAutoRefreshForTesting() { @@ -147,7 +144,7 @@ class RealmHandle extends HandleBase { } void close() { - realmLib.realm_close(pointer).raiseIfFalse("Realm close failed"); + realmLib.realm_close(pointer).raiseLastErrorIfFalse("Realm close failed"); } bool get isClosed { @@ -155,11 +152,11 @@ class RealmHandle extends HandleBase { } void beginWrite() { - realmLib.realm_begin_write(pointer).raiseIfFalse("Could not begin write"); + realmLib.realm_begin_write(pointer).raiseLastErrorIfFalse("Could not begin write"); } void commitWrite() { - realmLib.realm_commit(pointer).raiseIfFalse("Could not commit write"); + realmLib.realm_commit(pointer).raiseLastErrorIfFalse("Could not commit write"); } Future beginWriteAsync(CancellationToken? ct) { @@ -181,7 +178,7 @@ class RealmHandle extends HandleBase { true, transactionId, ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); id = transactionId.value; }); } @@ -207,7 +204,7 @@ class RealmHandle extends HandleBase { false, transactionId, ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); id = transactionId.value; }); } @@ -215,9 +212,9 @@ class RealmHandle extends HandleBase { } bool _cancelAsync(int cancellationId) { - return using((Arena arena) { + return using((arena) { final didCancel = arena(); - realmLib.realm_async_cancel(pointer, cancellationId, didCancel).raiseIfFalse(); + realmLib.realm_async_cancel(pointer, cancellationId, didCancel).raiseLastErrorIfFalse(); return didCancel.value; }); } @@ -241,13 +238,13 @@ class RealmHandle extends HandleBase { } void rollbackWrite() { - realmLib.realm_rollback(pointer).raiseIfFalse("Could not rollback write"); + realmLib.realm_rollback(pointer).raiseLastErrorIfFalse("Could not rollback write"); } bool refresh() { - return using((Arena arena) { + return using((arena) { final didRefresh = arena(); - realmLib.realm_refresh(pointer, didRefresh).raiseIfFalse("Could not refresh"); + realmLib.realm_refresh(pointer, didRefresh).raiseLastErrorIfFalse("Could not refresh"); return didRefresh.value; }); } @@ -276,30 +273,29 @@ class RealmHandle extends HandleBase { } ResultsHandle findAll(int classKey) { - final ptr = realmLib.realm_object_find_all(pointer, classKey).raiseIfNull(); - return ResultsHandle(ptr, this); + return ResultsHandle(realmLib.realm_object_find_all(pointer, classKey), this); } ObjectHandle? find(int classKey, Object? primaryKey) { - return using((Arena arena) { + return using((arena) { final realmValue = primaryKey.toNative(arena); final found = arena(); final ptr = realmLib.realm_object_find_with_primary_key(pointer, classKey, realmValue.ref, found); if (!found.value) { + assert(ptr == nullptr); // If not found, the pointer should be null. Otherwise we have a leak return null; } - return ObjectHandle(ptr.raiseIfNull(), this); + return ObjectHandle(ptr, this); }); } ObjectHandle? findExisting(int classKey, ObjectHandle other) { final key = realmLib.realm_object_get_key(other.pointer); - final ptr = realmLib.realm_get_object(pointer, classKey, key).raiseIfNull(); - return ObjectHandle(ptr, this); + return ObjectHandle(realmLib.realm_get_object(pointer, classKey, key), this); } void renameProperty(String objectType, String oldName, String newName, SchemaHandle schema) { - using((Arena arena) { + using((arena) { realmLib .realm_schema_rename_property( pointer, @@ -308,37 +304,36 @@ class RealmHandle extends HandleBase { oldName.toCharPtr(arena), newName.toCharPtr(arena), ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); }); } bool deleteType(String objectType) { - return using((Arena arena) { + return using((arena) { final tableDeleted = arena(); - realmLib.realm_remove_table(pointer, objectType.toCharPtr(arena), tableDeleted).raiseIfFalse(); + realmLib.realm_remove_table(pointer, objectType.toCharPtr(arena), tableDeleted).raiseLastErrorIfFalse(); return tableDeleted.value; }); } ObjectHandle getObject(int classKey, int objectKey) { - final ptr = realmLib.realm_get_object(pointer, classKey, objectKey).raiseIfNull(); - return ObjectHandle(ptr, this); + return ObjectHandle(realmLib.realm_get_object(pointer, classKey, objectKey), this); } CallbackTokenHandle subscribeForSchemaNotifications(Realm realm) { - final ptr = realmLib - .realm_add_schema_changed_callback( - pointer, - Pointer.fromFunction(_schemaChangeCallback), - realm.toPersistentHandle(), - realmLib.addresses.realm_dart_delete_persistent_handle, - ) - .raiseIfNull(); - return CallbackTokenHandle(ptr, this); + return CallbackTokenHandle( + realmLib.realm_add_schema_changed_callback( + pointer, + Pointer.fromFunction(_schemaChangeCallback), + realm.toPersistentHandle(), + realmLib.addresses.realm_dart_delete_persistent_handle, + ), + this, + ); } RealmSchema readSchema() { - return using((Arena arena) { + return using((arena) { return _readSchema(arena); }); } @@ -346,7 +341,7 @@ class RealmHandle extends HandleBase { RealmSchema _readSchema(Arena arena, {int expectedSize = 10}) { final classesPtr = arena(expectedSize); final actualCount = arena(); - realmLib.realm_get_class_keys(pointer, classesPtr, expectedSize, actualCount).raiseIfFalse(); + realmLib.realm_get_class_keys(pointer, classesPtr, expectedSize, actualCount).raiseLastErrorIfFalse(); if (expectedSize < actualCount.value) { arena.free(classesPtr); return _readSchema(arena, expectedSize: actualCount.value); @@ -356,7 +351,7 @@ class RealmHandle extends HandleBase { for (var i = 0; i < actualCount.value; i++) { final classInfo = arena(); final classKey = (classesPtr + i).value; - realmLib.realm_get_class(pointer, classKey, classInfo).raiseIfFalse(); + realmLib.realm_get_class(pointer, classKey, classInfo).raiseLastErrorIfFalse(); final name = classInfo.ref.name.cast().toDartString(); final baseType = ObjectType.values.firstWhere((element) => element.flags == classInfo.ref.flags, @@ -371,7 +366,7 @@ class RealmHandle extends HandleBase { SchemaObject _getSchemaForClassKey(int classKey, String name, ObjectType baseType, Arena arena, {int expectedSize = 10}) { final actualCount = arena(); final propertiesPtr = arena(expectedSize); - realmLib.realm_get_class_properties(pointer, classKey, propertiesPtr, expectedSize, actualCount).raiseIfFalse(); + realmLib.realm_get_class_properties(pointer, classKey, propertiesPtr, expectedSize, actualCount).raiseLastErrorIfFalse(); if (expectedSize < actualCount.value) { // The supplied array was too small - resize it @@ -404,20 +399,20 @@ class RealmHandle extends HandleBase { } Map getPropertiesMetadata(int classKey, String? primaryKeyName) { - return using((Arena arena) { + return using((arena) { return _getPropertiesMetadata(classKey, primaryKeyName, arena); }); } RealmObjectMetadata getObjectMetadata(SchemaObject schema) { - return using((Arena arena) { + return using((arena) { final found = arena(); final classInfo = arena(); - realmLib.realm_find_class(pointer, schema.name.toCharPtr(arena), found, classInfo).raiseIfFalse(); + realmLib.realm_find_class(pointer, schema.name.toCharPtr(arena), found, classInfo).raiseLastErrorIfFalse(); // "Error getting class ${schema.name} from realm at ${realm.config.path}"); if (!found.value) { - throwLastError(); //"Class ${schema.name} not found in ${realm.config.path}"); + raiseLastError(); //"Class ${schema.name} not found in ${realm.config.path}"); } final primaryKey = classInfo.ref.primary_key.cast().toRealmDartString(treatEmptyAsNull: true); @@ -427,11 +422,13 @@ class RealmHandle extends HandleBase { Map _getPropertiesMetadata(int classKey, String? primaryKeyName, Arena arena) { final propertyCountPtr = arena(); - realmLib.realm_get_property_keys(pointer, classKey, nullptr, 0, propertyCountPtr).raiseIfFalse("Error getting property count"); + realmLib.realm_get_property_keys(pointer, classKey, nullptr, 0, propertyCountPtr).raiseLastErrorIfFalse("Error getting property count"); var propertyCount = propertyCountPtr.value; final propertiesPtr = arena(propertyCount); - realmLib.realm_get_class_properties(pointer, classKey, propertiesPtr, propertyCount, propertyCountPtr).raiseIfFalse("Error getting class properties."); + realmLib + .realm_get_class_properties(pointer, classKey, propertiesPtr, propertyCount, propertyCountPtr) + .raiseLastErrorIfFalse("Error getting class properties."); propertyCount = propertyCountPtr.value; Map result = {}; diff --git a/packages/realm_dart/lib/src/native/results_handle.dart b/packages/realm_dart/lib/src/native/results_handle.dart index c21c7c2a3..60bac62ea 100644 --- a/packages/realm_dart/lib/src/native/results_handle.dart +++ b/packages/realm_dart/lib/src/native/results_handle.dart @@ -26,21 +26,20 @@ class ResultsHandle extends RootedHandleBase { intoRealmQueryArg(args[i], argsPointer + i, arena); } final queryHandle = QueryHandle( - realmLib - .realm_query_parse_for_results( - pointer, - query.toCharPtr(arena), - length, - argsPointer, - ) - .raiseIfNull(), - root); + realmLib.realm_query_parse_for_results( + pointer, + query.toCharPtr(arena), + length, + argsPointer, + ), + root, + ); return queryHandle.findAll(); }); } int find(Object? value) { - return using((Arena arena) { + return using((arena) { final outIndex = arena(); final outFound = arena(); @@ -53,20 +52,19 @@ class ResultsHandle extends RootedHandleBase { outIndex, outFound, ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); return outFound.value ? outIndex.value : -1; }); } ObjectHandle getObjectAt(int index) { - final objectPointer = realmLib.realm_results_get_object(pointer, index).raiseIfNull(); - return ObjectHandle(objectPointer, root); + return ObjectHandle(realmLib.realm_results_get_object(pointer, index), root); } int get count { - return using((Arena arena) { + return using((arena) { final countPtr = arena(); - realmLib.realm_results_count(pointer, countPtr).raiseIfFalse(); + realmLib.realm_results_count(pointer, countPtr).raiseLastErrorIfFalse(); return countPtr.value; }); } @@ -74,29 +72,27 @@ class ResultsHandle extends RootedHandleBase { bool isValid() { return using((arena) { final isValid = arena(); - realmLib.realm_results_is_valid(pointer, isValid).raiseIfFalse(); + realmLib.realm_results_is_valid(pointer, isValid).raiseLastErrorIfFalse(); return isValid.value; }); } void deleteAll() { - realmLib.realm_results_delete_all(pointer).raiseIfFalse(); + realmLib.realm_results_delete_all(pointer).raiseLastErrorIfFalse(); } ResultsHandle snapshot() { - final resultsPointer = realmLib.realm_results_snapshot(pointer).raiseIfNull(); - return ResultsHandle(resultsPointer, root); + return ResultsHandle(realmLib.realm_results_snapshot(pointer), root); } ResultsHandle resolveIn(RealmHandle realmHandle) { - final ptr = realmLib.realm_results_resolve_in(pointer, realmHandle.pointer).raiseIfNull(); - return ResultsHandle(ptr, realmHandle); + return ResultsHandle(realmLib.realm_results_resolve_in(pointer, realmHandle.pointer), realmHandle); } Object? elementAt(Realm realm, int index) { - return using((Arena arena) { + return using((arena) { final realmValue = arena(); - realmLib.realm_results_get(pointer, index, realmValue).raiseIfFalse(); + realmLib.realm_results_get(pointer, index, realmValue).raiseLastErrorIfFalse(); return realmValue.toDartValue( realm, () => realmLib.realm_results_get_list(pointer, index), @@ -106,15 +102,15 @@ class ResultsHandle extends RootedHandleBase { } NotificationTokenHandle subscribeForNotifications(NotificationsController controller) { - final ptr = realmLib - .realm_results_add_notification_callback( - pointer, - controller.toPersistentHandle(), - realmLib.addresses.realm_dart_delete_persistent_handle, - nullptr, - Pointer.fromFunction(collectionChangeCallback), - ) - .raiseIfNull(); - return NotificationTokenHandle(ptr, root); + return NotificationTokenHandle( + realmLib.realm_results_add_notification_callback( + pointer, + controller.toPersistentHandle(), + realmLib.addresses.realm_dart_delete_persistent_handle, + nullptr, + Pointer.fromFunction(collectionChangeCallback), + ), + root, + ); } } diff --git a/packages/realm_dart/lib/src/native/schema_handle.dart b/packages/realm_dart/lib/src/native/schema_handle.dart index a92ae7ca8..588d0496f 100644 --- a/packages/realm_dart/lib/src/native/schema_handle.dart +++ b/packages/realm_dart/lib/src/native/schema_handle.dart @@ -8,7 +8,6 @@ import 'package:realm_common/realm_common.dart'; import 'package:realm_dart/src/native/realm_core.dart'; import '../configuration.dart'; -import 'error_handling.dart'; import 'handle_base.dart'; import 'realm_bindings.dart'; import 'realm_library.dart'; @@ -19,7 +18,7 @@ class SchemaHandle extends HandleBase { SchemaHandle.unowned(super.pointer) : super.unowned(); factory SchemaHandle.from(Iterable schema) { - return using((Arena arena) { + return using((arena) { final classCount = schema.length; final schemaClasses = arena(classCount); @@ -77,8 +76,7 @@ class SchemaHandle extends HandleBase { (schemaProperties + i).value = properties; } - final schemaPtr = realmLib.realm_schema_new(schemaClasses, classCount, schemaProperties).raiseIfNull(); - return SchemaHandle(schemaPtr); + return SchemaHandle(realmLib.realm_schema_new(schemaClasses, classCount, schemaProperties)); }); } } diff --git a/packages/realm_dart/lib/src/native/session_handle.dart b/packages/realm_dart/lib/src/native/session_handle.dart index 30e18966b..cda7a2676 100644 --- a/packages/realm_dart/lib/src/native/session_handle.dart +++ b/packages/realm_dart/lib/src/native/session_handle.dart @@ -9,7 +9,6 @@ import 'package:ffi/ffi.dart'; import '../realm_dart.dart'; import '../scheduler.dart'; import '../session.dart'; // TODO: Remove this import -import 'error_handling.dart'; import 'handle_base.dart'; import 'realm_bindings.dart'; import 'realm_core.dart'; // TODO: Remove this import @@ -117,15 +116,14 @@ class SessionHandle extends RootedHandleBase { SyncSessionNotificationTokenHandle subscribeForConnectionStateNotifications(SessionConnectionStateController controller) { final callback = Pointer.fromFunction(_onConnectionStateChange); final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); - final ptr = realmLib - .realm_sync_session_register_connection_state_change_callback( - pointer, - realmLib.addresses.realm_dart_sync_connection_state_changed_callback, - userdata.cast(), - realmLib.addresses.realm_dart_userdata_async_free, - ) - .raiseIfNull(); - return SyncSessionNotificationTokenHandle(ptr); + return SyncSessionNotificationTokenHandle( + realmLib.realm_sync_session_register_connection_state_change_callback( + pointer, + realmLib.addresses.realm_dart_sync_connection_state_changed_callback, + userdata.cast(), + realmLib.addresses.realm_dart_userdata_async_free, + ), + ); } SyncSessionNotificationTokenHandle subscribeForProgressNotifications( @@ -136,11 +134,16 @@ class SessionHandle extends RootedHandleBase { final isStreaming = mode == ProgressMode.reportIndefinitely; final callback = Pointer.fromFunction(syncProgressCallback); final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); - final tokenPtr = realmLib - .realm_sync_session_register_progress_notifier(pointer, realmLib.addresses.realm_dart_sync_progress_callback, direction.index, isStreaming, - userdata.cast(), realmLib.addresses.realm_dart_userdata_async_free) - .raiseIfNull(); - return SyncSessionNotificationTokenHandle(tokenPtr); + return SyncSessionNotificationTokenHandle( + realmLib.realm_sync_session_register_progress_notifier( + pointer, + realmLib.addresses.realm_dart_sync_progress_callback, + direction.index, + isStreaming, + userdata.cast(), + realmLib.addresses.realm_dart_userdata_async_free, + ), + ); } } diff --git a/packages/realm_dart/lib/src/native/set_handle.dart b/packages/realm_dart/lib/src/native/set_handle.dart index 0ddcef6fa..668b6255b 100644 --- a/packages/realm_dart/lib/src/native/set_handle.dart +++ b/packages/realm_dart/lib/src/native/set_handle.dart @@ -19,8 +19,7 @@ class SetHandle extends RootedHandleBase { SetHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 96); ResultsHandle get asResults { - final ptr = realmLib.realm_set_to_results(pointer).raiseIfNull(); - return ResultsHandle(ptr, root); + return ResultsHandle(realmLib.realm_set_to_results(pointer), root); } ResultsHandle query(String query, List args) { @@ -31,34 +30,33 @@ class SetHandle extends RootedHandleBase { intoRealmQueryArg(args[i], argsPointer + i, arena); } final queryHandle = QueryHandle( - realmLib - .realm_query_parse_for_set( - pointer, - query.toCharPtr(arena), - length, - argsPointer, - ) - .raiseIfNull(), - root); + realmLib.realm_query_parse_for_set( + pointer, + query.toCharPtr(arena), + length, + argsPointer, + ), + root, + ); return queryHandle.findAll(); }); } bool insert(Object? value) { - return using((Arena arena) { + return using((arena) { final realmValue = value.toNative(arena); final outIndex = arena(); final outInserted = arena(); - realmLib.realm_set_insert(pointer, realmValue.ref, outIndex, outInserted).raiseIfFalse(); + realmLib.realm_set_insert(pointer, realmValue.ref, outIndex, outInserted).raiseLastErrorIfFalse(); return outInserted.value; }); } // TODO: avoid taking the [realm] parameter Object? elementAt(Realm realm, int index) { - return using((Arena arena) { + return using((arena) { final realmValue = arena(); - realmLib.realm_set_get(pointer, index, realmValue).raiseIfFalse(); + realmLib.realm_set_get(pointer, index, realmValue).raiseLastErrorIfFalse(); final result = realmValue.toDartValue( realm, () => throw RealmException('Sets cannot contain collections'), @@ -69,34 +67,34 @@ class SetHandle extends RootedHandleBase { } bool find(Object? value) { - return using((Arena arena) { + return using((arena) { // TODO: how should this behave for collections final realmValue = value.toNative(arena); final outIndex = arena(); final outFound = arena(); - realmLib.realm_set_find(pointer, realmValue.ref, outIndex, outFound).raiseIfFalse(); + realmLib.realm_set_find(pointer, realmValue.ref, outIndex, outFound).raiseLastErrorIfFalse(); return outFound.value; }); } bool remove(Object? value) { - return using((Arena arena) { + return using((arena) { // TODO: do we support sets containing mixed collections final realmValue = value.toNative(arena); final outErased = arena(); - realmLib.realm_set_erase(pointer, realmValue.ref, outErased).raiseIfFalse(); + realmLib.realm_set_erase(pointer, realmValue.ref, outErased).raiseLastErrorIfFalse(); return outErased.value; }); } void clear() { - realmLib.realm_set_clear(pointer).raiseIfFalse(); + realmLib.realm_set_clear(pointer).raiseLastErrorIfFalse(); } int get size { - return using((Arena arena) { + return using((arena) { final outSize = arena(); - realmLib.realm_set_size(pointer, outSize).raiseIfFalse(); + realmLib.realm_set_size(pointer, outSize).raiseLastErrorIfFalse(); return outSize.value; }); } @@ -106,27 +104,27 @@ class SetHandle extends RootedHandleBase { } void deleteAll() { - realmLib.realm_set_remove_all(pointer).raiseIfFalse(); + realmLib.realm_set_remove_all(pointer).raiseLastErrorIfFalse(); } SetHandle? resolveIn(RealmHandle frozenRealm) { - return using((Arena arena) { + return using((arena) { final resultPtr = arena>(); - realmLib.realm_set_resolve_in(pointer, frozenRealm.pointer, resultPtr).raiseIfFalse(); + realmLib.realm_set_resolve_in(pointer, frozenRealm.pointer, resultPtr).raiseLastErrorIfFalse(); return resultPtr == nullptr ? null : SetHandle(resultPtr.value, root); }); } NotificationTokenHandle subscribeForNotifications(NotificationsController controller) { - final ptr = realmLib - .realm_set_add_notification_callback( - pointer, - controller.toPersistentHandle(), - realmLib.addresses.realm_dart_delete_persistent_handle, - nullptr, - Pointer.fromFunction(collectionChangeCallback), - ) - .raiseIfNull(); - return NotificationTokenHandle(ptr, root); + return NotificationTokenHandle( + realmLib.realm_set_add_notification_callback( + pointer, + controller.toPersistentHandle(), + realmLib.addresses.realm_dart_delete_persistent_handle, + nullptr, + Pointer.fromFunction(collectionChangeCallback), + ), + root, + ); } } diff --git a/packages/realm_dart/lib/src/native/subscription_set_handle.dart b/packages/realm_dart/lib/src/native/subscription_set_handle.dart index 0725f6626..a96cff307 100644 --- a/packages/realm_dart/lib/src/native/subscription_set_handle.dart +++ b/packages/realm_dart/lib/src/native/subscription_set_handle.dart @@ -25,7 +25,7 @@ class SubscriptionSetHandle extends RootedHandleBase pointer, RealmHandle root) : super(root, pointer, 128); - void refresh() => realmLib.realm_sync_subscription_set_refresh(pointer).raiseIfFalse(); + void refresh() => realmLib.realm_sync_subscription_set_refresh(pointer).raiseLastErrorIfFalse(); int get size => realmLib.realm_sync_subscription_set_size(pointer); @@ -35,7 +35,7 @@ class SubscriptionSetHandle extends RootedHandleBase SubscriptionHandle(realmLib.realm_sync_subscription_at(pointer, index).raiseIfNull()); + SubscriptionHandle operator [](int index) => SubscriptionHandle(realmLib.realm_sync_subscription_at(pointer, index)); SubscriptionHandle? findByName(String name) { return using((arena) { @@ -59,7 +59,7 @@ class SubscriptionSetHandle extends RootedHandleBase SubscriptionSetState.values[realmLib.realm_sync_subscription_set_state(pointer)]; - MutableSubscriptionSetHandle toMutable() => MutableSubscriptionSetHandle(realmLib.realm_sync_make_subscription_set_mutable(pointer).raiseIfNull(), root); + MutableSubscriptionSetHandle toMutable() => MutableSubscriptionSetHandle(realmLib.realm_sync_make_subscription_set_mutable(pointer), root); static void _stateChangeCallback(Object userdata, int state) { final completer = userdata as CancellableCompleter; diff --git a/packages/realm_dart/lib/src/native/user_handle.dart b/packages/realm_dart/lib/src/native/user_handle.dart index 9fc14b992..5dd58fc95 100644 --- a/packages/realm_dart/lib/src/native/user_handle.dart +++ b/packages/realm_dart/lib/src/native/user_handle.dart @@ -6,6 +6,7 @@ import 'dart:convert'; import 'dart:ffi'; import 'package:ffi/ffi.dart'; +import 'package:realm_dart/src/app.dart'; import '../credentials.dart'; // TODO: Remove this import import '../realm_dart.dart'; // TODO: Remove this import @@ -34,7 +35,7 @@ class UserHandle extends HandleBase { } String get id { - final idPtr = realmLib.realm_user_get_identity(pointer).raiseIfNull("Error while getting user id"); + final idPtr = realmLib.realm_user_get_identity(pointer)..raiseLastErrorIfNull("Error while getting user id"); final userId = idPtr.cast().toDartString(); return userId; } @@ -48,7 +49,7 @@ class UserHandle extends HandleBase { List _userGetIdentities(Arena arena, {int expectedSize = 2}) { final actualCount = arena(); final identitiesPtr = arena(expectedSize); - realmLib.realm_user_get_all_identities(pointer, identitiesPtr, expectedSize, actualCount).raiseIfFalse(); + realmLib.realm_user_get_all_identities(pointer, identitiesPtr, expectedSize, actualCount).raiseLastErrorIfFalse(); if (expectedSize < actualCount.value) { // The supplied array was too small - resize it @@ -68,32 +69,32 @@ class UserHandle extends HandleBase { } Future logOut() async { - realmLib.realm_user_log_out(pointer).raiseIfFalse("Logout failed"); + realmLib.realm_user_log_out(pointer).raiseLastErrorIfFalse("Logout failed"); } String? get deviceId { - final deviceId = realmLib.realm_user_get_device_id(pointer).raiseIfNull(); + final deviceId = realmLib.realm_user_get_device_id(pointer)..raiseLastErrorIfNull(); return deviceId.cast().toRealmDartString(treatEmptyAsNull: true, freeRealmMemory: true); } UserProfile get profileData { - final data = realmLib.realm_user_get_profile_data(pointer).raiseIfNull(); + final data = realmLib.realm_user_get_profile_data(pointer)..raiseLastErrorIfNull(); final dynamic profileData = jsonDecode(data.cast().toRealmDartString(freeRealmMemory: true)!); return UserProfile(profileData as Map); } String get refreshToken { - final token = realmLib.realm_user_get_refresh_token(pointer).raiseIfNull(); + final token = realmLib.realm_user_get_refresh_token(pointer)..raiseLastErrorIfNull(); return token.cast().toRealmDartString(freeRealmMemory: true)!; } String get accessToken { - final token = realmLib.realm_user_get_access_token(pointer).raiseIfNull(); + final token = realmLib.realm_user_get_access_token(pointer)..raiseLastErrorIfNull(); return token.cast().toRealmDartString(freeRealmMemory: true)!; } String get path { - final syncConfigPtr = realmLib.realm_flx_sync_config_new(pointer).raiseIfNull(); + final syncConfigPtr = realmLib.realm_flx_sync_config_new(pointer)..raiseLastErrorIfNull(); try { final path = realmLib.realm_app_sync_client_get_default_file_path_for_realm(syncConfigPtr, nullptr); return path.cast().toRealmDartString(freeRealmMemory: true)!; @@ -118,12 +119,12 @@ class UserHandle extends HandleBase { createAsyncUserCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseIfFalse("Link credentials failed"); + .raiseLastErrorIfFalse("Link credentials failed"); return completer.future; } Future createApiKey(AppHandle app, String name) { - return using((Arena arena) { + return using((arena) { final namePtr = name.toCharPtr(arena); final completer = Completer(); realmLib @@ -135,14 +136,14 @@ class UserHandle extends HandleBase { _createAsyncApikeyCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); return completer.future; }); } Future fetchApiKey(AppHandle app, ObjectId id) { - return using((Arena arena) { + return using((arena) { final completer = Completer(); final nativeId = id.toNative(arena); realmLib @@ -154,14 +155,14 @@ class UserHandle extends HandleBase { _createAsyncApikeyCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); return completer.future; }); } Future> fetchAllApiKeys(AppHandle app) { - return using((Arena arena) { + return using((arena) { final completer = Completer>(); realmLib .realm_app_user_apikey_provider_client_fetch_apikeys( @@ -171,14 +172,14 @@ class UserHandle extends HandleBase { _createAsyncApikeyListCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); return completer.future; }); } Future deleteApiKey(AppHandle app, ObjectId id) { - return using((Arena arena) { + return using((arena) { final completer = Completer(); final nativeId = id.toNative(arena); realmLib @@ -190,14 +191,14 @@ class UserHandle extends HandleBase { createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); return completer.future; }); } Future disableApiKey(AppHandle app, ObjectId objectId) { - return using((Arena arena) { + return using((arena) { final completer = Completer(); final nativeId = objectId.toNative(arena); @@ -210,14 +211,14 @@ class UserHandle extends HandleBase { createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); return completer.future; }); } Future enableApiKey(AppHandle app, ObjectId objectId) { - return using((Arena arena) { + return using((arena) { final completer = Completer(); final nativeId = objectId.toNative(arena); @@ -230,7 +231,7 @@ class UserHandle extends HandleBase { createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseIfFalse(); + .raiseLastErrorIfFalse(); return completer.future; }); From 82a0330c995793ca1dbb765571563d5dd81dae5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Mon, 6 May 2024 10:22:19 +0200 Subject: [PATCH 58/68] Completely unrelated spelling corrections in CHANGELOG --- CHANGELOG.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8986c3bbe..922c56f04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -82,7 +82,7 @@ * Fixed a `DecryptionFailed` exception thrown when opening a small (<4k of data) Realm generated on a device with a page size of 4k if it was bundled and opened on a device with a larger page size. * Fixed an issue during a subsequent open of an encrypted Realm for some rare allocation patterns when the top ref was within ~50 bytes of the end of a page. This could manifest as a DecryptionFailed exception or as an assertion: `encrypted_file_mapping.hpp:183: Assertion failed: local_ndx < m_page_state.size()`. * Schema initialization could hit an assertion failure if the sync client applied a downloaded changeset while the Realm file was in the process of being opened. (Core 14.6.0) -* Improve perfomance of "chained OR equality" queries for UUID/ObjectId types and RQL parsed "IN" queries on string/int/uuid/objectid types. (Core 14.6.0) +* Improve performance of "chained OR equality" queries for UUID/ObjectId types and RQL parsed "IN" queries on string/int/uuid/objectid types. (Core 14.6.0) * Fixed a bug when running a IN query (or a query of the pattern `x == 1 OR x == 2 OR x == 3`) when evaluating on a string property with an empty string in the search condition. Matches with an empty string would have been evaluated as if searching for a null string instead. (Core 14.6.2) ### Compatibility @@ -184,9 +184,9 @@ ``` * Removed `SchemaObject.properties` - instead, `SchemaObject` is now an iterable collection of `Property`. (Issue [#1449](https://github.com/realm/realm-dart/issues/1449)) * `SyncProgress.transferredBytes` and `SyncProgress.transferableBytes` have been consolidated into `SyncProgress.progressEstimate`. The values reported previously were incorrect and did not accurately represent bytes either. The new field better conveys the uncertainty around the progress being reported. With this release, we're reporting accurate estimates for upload progress, but estimating downloads is still unreliable. A future server and SDK release will add better estimations for download progress. (Issue [#1562](https://github.com/realm/realm-dart/issues/1562)) -* `Realm.logger` is no longer settable, and no longer implements `Logger` from package `logging`. In particular you can no longer call `Realm.logger.level =`. Instead you should call `Realm.logger.setLogLevel(RealmLogLevel level, {RealmLogCategory? category})` that takes an optional category. If no category is exlicitly given, then `RealmLogCategory.realm` is assumed. +* `Realm.logger` is no longer settable, and no longer implements `Logger` from package `logging`. In particular you can no longer call `Realm.logger.level =`. Instead you should call `Realm.logger.setLogLevel(RealmLogLevel level, {RealmLogCategory? category})` that takes an optional category. If no category is explicitly given, then `RealmLogCategory.realm` is assumed. - Also, note that setting a level is no longer local to the current isolate, but shared accross all isolates. At the core level there is just one process wide logger. + Also, note that setting a level is no longer local to the current isolate, but shared across all isolates. At the core level there is just one process wide logger. Categories form a hierarchy and setting the log level of a parent category will override the level of its children. The hierarchy is exposed in a type safe manner with: ```dart @@ -928,7 +928,7 @@ class _Address { * Queries on results didn't filter the existing results. ([#908](https://github.com/realm/realm-dart/issues/908)). Example ```dart - expect(realm.query('FALSEPREDICATE').query('TRUEPREDICATE'), isEmpty); //<-- Fails if a Persion object exists + expect(realm.query('FALSEPREDICATE').query('TRUEPREDICATE'), isEmpty); //<-- Fails if a Person object exists ``` * Fixed copying of native structs for session errors and http requests. ([#924](https://github.com/realm/realm-dart/pull/924)) * Fixed a crash when closing the SyncSession on App instance teardown. ([#5752](https://github.com/realm/realm-core/issues/5752)) @@ -1091,7 +1091,7 @@ class _Address { ```dart final subscription = realm.all().changes.listen((changes) { - changes.inserted // indexes of inserted ojbects + changes.inserted // indexes of inserted objects changes.modified // indexes of modified objects changes.deleted // indexes of deleted objects changes.newModified // indexes of modified objects after deletions and insertions are accounted for. @@ -1231,7 +1231,7 @@ Notes: This release is a prerelease version. All API's might change without warn Notes: This release is a prerelease version. All API's might change without warning and no guarantees are given about stability. ### Enhancements -* Completеly rewritten from the ground up with sound null safety and using Dart FFI +* Completely rewritten from the ground up with sound null safety and using Dart FFI ### Fixed * Realm close stops internal scheduler. @@ -1247,7 +1247,7 @@ Notes: This release is a prerelease version. All API's might change without warn Notes: This release is a prerelease version. All API's might change without warning and no guarantees are given about stability. ### Enhancements -* Completеly rewritten from the ground up with sound null safety and using Dart FFI +* Completely rewritten from the ground up with sound null safety and using Dart FFI ### Compatibility * Dart ^2.15 on Windows, MacOS and Linux From defc5aea6b0f239bd8d304d7e5f217f2f725c26e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Mon, 6 May 2024 11:02:21 +0200 Subject: [PATCH 59/68] Seperate AsyncOpenTaskHandle and NotificationHandle from realm_core.dart --- packages/realm_dart/lib/src/list.dart | 2 +- packages/realm_dart/lib/src/map.dart | 2 +- .../src/native/async_open_task_handle.dart | 80 +++++++++++++++++ .../lib/src/native/error_handling.dart | 1 - .../lib/src/native/list_handle.dart | 1 + .../realm_dart/lib/src/native/map_handle.dart | 1 + .../src/native/notification_token_handle.dart | 10 +++ .../lib/src/native/object_handle.dart | 1 + .../realm_dart/lib/src/native/realm_core.dart | 87 ++----------------- .../lib/src/native/results_handle.dart | 1 + .../realm_dart/lib/src/native/set_handle.dart | 1 + .../lib/src/native/user_handle.dart | 1 - packages/realm_dart/lib/src/realm_class.dart | 10 ++- packages/realm_dart/lib/src/realm_object.dart | 2 +- packages/realm_dart/lib/src/results.dart | 2 +- packages/realm_dart/lib/src/set.dart | 2 +- 16 files changed, 115 insertions(+), 89 deletions(-) create mode 100644 packages/realm_dart/lib/src/native/async_open_task_handle.dart create mode 100644 packages/realm_dart/lib/src/native/notification_token_handle.dart diff --git a/packages/realm_dart/lib/src/list.dart b/packages/realm_dart/lib/src/list.dart index 187aa3c46..be64591cb 100644 --- a/packages/realm_dart/lib/src/list.dart +++ b/packages/realm_dart/lib/src/list.dart @@ -12,8 +12,8 @@ import 'collections.dart'; import 'native/collection_changes_handle.dart'; import 'native/handle_base.dart'; import 'native/list_handle.dart'; +import 'native/notification_token_handle.dart'; import 'native/object_handle.dart'; -import 'native/realm_core.dart'; import 'realm_class.dart'; import 'realm_object.dart'; import 'results.dart'; diff --git a/packages/realm_dart/lib/src/map.dart b/packages/realm_dart/lib/src/map.dart index 99e47ddee..9e02bfb49 100644 --- a/packages/realm_dart/lib/src/map.dart +++ b/packages/realm_dart/lib/src/map.dart @@ -12,8 +12,8 @@ import 'collections.dart'; import 'native/handle_base.dart'; import 'native/map_changes_handle.dart'; import 'native/map_handle.dart'; +import 'native/notification_token_handle.dart'; import 'native/object_handle.dart'; -import 'native/realm_core.dart'; import 'realm_object.dart'; import 'realm_class.dart'; import 'results.dart'; diff --git a/packages/realm_dart/lib/src/native/async_open_task_handle.dart b/packages/realm_dart/lib/src/native/async_open_task_handle.dart new file mode 100644 index 000000000..c3cd2b1dd --- /dev/null +++ b/packages/realm_dart/lib/src/native/async_open_task_handle.dart @@ -0,0 +1,80 @@ +import 'dart:ffi'; + +import 'package:cancellation_token/cancellation_token.dart'; +import 'package:ffi/ffi.dart'; +import 'package:realm_dart/src/native/error_handling.dart'; +import 'package:realm_dart/src/native/realm_bindings.dart'; + +import '../realm_dart.dart'; +import '../scheduler.dart'; +import 'config_handle.dart'; +import 'handle_base.dart'; +import 'realm_handle.dart'; +import 'realm_library.dart'; +import 'session_handle.dart'; + +class AsyncOpenTaskHandle extends HandleBase { + AsyncOpenTaskHandle(Pointer pointer) : super(pointer, 32); + + factory AsyncOpenTaskHandle.from(FlexibleSyncConfiguration config) { + final configHandle = ConfigHandle.from(config); + final asyncOpenTaskPtr = realmLib.realm_open_synchronized(configHandle.pointer)..raiseLastErrorIfNull("Error opening realm at path ${config.path}"); + return AsyncOpenTaskHandle(asyncOpenTaskPtr); + } + + Future openAsync(CancellationToken? cancellationToken) { + final completer = CancellableCompleter(cancellationToken); + if (!completer.isCancelled) { + final callback = + Pointer.fromFunction realm, Pointer error)>(_openRealmAsyncCallback); + final userData = realmLib.realm_dart_userdata_async_new(completer, callback.cast(), scheduler.handle.pointer); + realmLib.realm_async_open_task_start( + pointer, + realmLib.addresses.realm_dart_async_open_task_callback, + userData.cast(), + realmLib.addresses.realm_dart_userdata_async_free, + ); + } + return completer.future; + } + + void cancel() { + realmLib.realm_async_open_task_cancel(pointer); + } + + AsyncOpenTaskProgressNotificationTokenHandle registerProgressNotifier( + RealmAsyncOpenProgressNotificationsController controller, + ) { + final callback = Pointer.fromFunction(syncProgressCallback); + final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); + return AsyncOpenTaskProgressNotificationTokenHandle( + realmLib.realm_async_open_task_register_download_progress_notifier( + pointer, + realmLib.addresses.realm_dart_sync_progress_callback, + userdata.cast(), + realmLib.addresses.realm_dart_userdata_async_free, + ), + ); + } +} + +class AsyncOpenTaskProgressNotificationTokenHandle extends HandleBase { + AsyncOpenTaskProgressNotificationTokenHandle(Pointer pointer) : super(pointer, 40); +} + +void _openRealmAsyncCallback(Object userData, Pointer realmSafePtr, Pointer error) { + return using((arena) { + final completer = userData as CancellableCompleter; + if (completer.isCancelled) { + return; + } + if (error != nullptr) { + final err = arena(); + final lastError = realmLib.realm_get_async_error(error, err) ? err.ref.toDart() : null; + completer.completeError(RealmException("Failed to open realm: ${lastError?.message ?? 'Error details missing.'}")); + return; + } + + completer.complete(RealmHandle(realmLib.realm_from_thread_safe_reference(realmSafePtr, scheduler.handle.pointer))); + }); +} diff --git a/packages/realm_dart/lib/src/native/error_handling.dart b/packages/realm_dart/lib/src/native/error_handling.dart index ae8e079ea..1faae1930 100644 --- a/packages/realm_dart/lib/src/native/error_handling.dart +++ b/packages/realm_dart/lib/src/native/error_handling.dart @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 import 'dart:ffi'; -import 'dart:io'; import 'package:ffi/ffi.dart'; diff --git a/packages/realm_dart/lib/src/native/list_handle.dart b/packages/realm_dart/lib/src/native/list_handle.dart index 1fa5b7161..b8f12ee1e 100644 --- a/packages/realm_dart/lib/src/native/list_handle.dart +++ b/packages/realm_dart/lib/src/native/list_handle.dart @@ -7,6 +7,7 @@ import 'package:ffi/ffi.dart'; import '../realm_dart.dart'; import 'error_handling.dart'; +import 'notification_token_handle.dart'; import 'object_handle.dart'; import 'query_handle.dart'; import 'realm_bindings.dart'; diff --git a/packages/realm_dart/lib/src/native/map_handle.dart b/packages/realm_dart/lib/src/native/map_handle.dart index f23f502d2..c974d3553 100644 --- a/packages/realm_dart/lib/src/native/map_handle.dart +++ b/packages/realm_dart/lib/src/native/map_handle.dart @@ -8,6 +8,7 @@ import 'package:ffi/ffi.dart'; import '../realm_dart.dart'; // TODO: remove this import import 'error_handling.dart'; import 'map_changes_handle.dart'; +import 'notification_token_handle.dart'; import 'object_handle.dart'; import 'query_handle.dart'; import 'realm_bindings.dart'; diff --git a/packages/realm_dart/lib/src/native/notification_token_handle.dart b/packages/realm_dart/lib/src/native/notification_token_handle.dart new file mode 100644 index 000000000..9d02ac649 --- /dev/null +++ b/packages/realm_dart/lib/src/native/notification_token_handle.dart @@ -0,0 +1,10 @@ +import 'dart:ffi'; + +import 'realm_bindings.dart'; +import 'realm_handle.dart'; +import 'rooted_handle.dart'; + +class NotificationTokenHandle extends RootedHandleBase { + NotificationTokenHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 32); +} + diff --git a/packages/realm_dart/lib/src/native/object_handle.dart b/packages/realm_dart/lib/src/native/object_handle.dart index 979e09718..a5bcefc3e 100644 --- a/packages/realm_dart/lib/src/native/object_handle.dart +++ b/packages/realm_dart/lib/src/native/object_handle.dart @@ -10,6 +10,7 @@ import 'error_handling.dart'; import 'handle_base.dart'; import 'list_handle.dart'; import 'map_handle.dart'; +import 'notification_token_handle.dart'; import 'realm_bindings.dart'; import 'realm_core.dart'; // TODO: Remove this import import 'realm_handle.dart'; diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 3fc1a6fd2..b181c942d 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -7,12 +7,12 @@ import 'dart:ffi'; import 'dart:io'; import 'dart:typed_data'; -import 'package:cancellation_token/cancellation_token.dart'; import 'package:crypto/crypto.dart'; // Hide StringUtf8Pointer.toNativeUtf8 and StringUtf16Pointer since these allows silently allocating memory. Use toUtf8Ptr instead import 'package:ffi/ffi.dart' hide StringUtf8Pointer, StringUtf16Pointer; import 'package:path/path.dart' as path; import 'package:pubspec_parse/pubspec_parse.dart'; +import 'package:realm_dart/src/native/convert.dart'; import '../app.dart'; import '../configuration.dart'; @@ -23,17 +23,13 @@ import '../scheduler.dart'; import '../user.dart'; import 'app_handle.dart'; import 'collection_changes_handle.dart'; -import 'config_handle.dart'; import 'decimal128.dart'; import 'error_handling.dart'; -import 'handle_base.dart'; import 'list_handle.dart'; import 'map_handle.dart'; import 'realm_bindings.dart'; -import 'realm_handle.dart'; import 'realm_library.dart'; import 'rooted_handle.dart'; -import 'session_handle.dart'; final _pluginLib = () { if (!isFlutterPlatform) { @@ -218,65 +214,6 @@ class _RealmCore { realmLib.realm_scheduler_perform_work(queuePointer); } - AsyncOpenTaskHandle createRealmAsyncOpenTask(FlexibleSyncConfiguration config) { - final configHandle = ConfigHandle.from(config); - final asyncOpenTaskPtr = realmLib.realm_open_synchronized(configHandle.pointer)..raiseLastErrorIfNull("Error opening realm at path ${config.path}"); - return AsyncOpenTaskHandle(asyncOpenTaskPtr); - } - - Future openRealmAsync(AsyncOpenTaskHandle handle, CancellationToken? cancellationToken) { - final completer = CancellableCompleter(cancellationToken); - if (!completer.isCancelled) { - final callback = - Pointer.fromFunction realm, Pointer error)>(openRealmAsyncCallback); - final userData = realmLib.realm_dart_userdata_async_new(completer, callback.cast(), scheduler.handle.pointer); - realmLib.realm_async_open_task_start( - handle.pointer, - realmLib.addresses.realm_dart_async_open_task_callback, - userData.cast(), - realmLib.addresses.realm_dart_userdata_async_free, - ); - } - return completer.future; - } - - static void openRealmAsyncCallback(Object userData, Pointer realmSafePtr, Pointer error) { - return using((arena) { - final completer = userData as CancellableCompleter; - if (completer.isCancelled) { - return; - } - if (error != nullptr) { - final err = arena(); - final lastError = realmLib.realm_get_async_error(error, err) ? err.ref.toDart() : null; - completer.completeError(RealmException("Failed to open realm: ${lastError?.message ?? 'Error details missing.'}")); - return; - } - - completer.complete(RealmHandle(realmLib.realm_from_thread_safe_reference(realmSafePtr, scheduler.handle.pointer))); - }); - } - - void cancelOpenRealmAsync(AsyncOpenTaskHandle handle) { - realmLib.realm_async_open_task_cancel(handle.pointer); - } - - AsyncOpenTaskProgressNotificationTokenHandle realmAsyncOpenRegisterAsyncOpenProgressNotifier( - AsyncOpenTaskHandle handle, - RealmAsyncOpenProgressNotificationsController controller, - ) { - final callback = Pointer.fromFunction(syncProgressCallback); - final userdata = realmLib.realm_dart_userdata_async_new(controller, callback.cast(), scheduler.handle.pointer); - return AsyncOpenTaskProgressNotificationTokenHandle( - realmLib.realm_async_open_task_register_download_progress_notifier( - handle.pointer, - realmLib.addresses.realm_dart_sync_progress_callback, - userdata.cast(), - realmLib.addresses.realm_dart_userdata_async_free, - ), - ); - } - void deleteRealmFiles(String path) { using((arena) { final realmDeleted = arena(); @@ -301,8 +238,14 @@ class _RealmCore { AppHandle? getApp(String id, String? baseUrl) { return using((arena) { final outApp = arena>(); - realmLib.realm_app_get_cached(id.toCharPtr(arena), baseUrl == null ? nullptr : baseUrl.toCharPtr(arena), outApp).raiseLastErrorIfFalse(); - return outApp.value == nullptr ? null : AppHandle(outApp.value); + realmLib + .realm_app_get_cached( + id.toCharPtr(arena), + baseUrl == null ? nullptr : baseUrl.toCharPtr(arena), + outApp, + ) + .raiseLastErrorIfFalse(); + return outApp.value.convert(AppHandle.new); }); } @@ -367,18 +310,6 @@ class _RealmCore { } } -class NotificationTokenHandle extends RootedHandleBase { - NotificationTokenHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 32); -} - -class AsyncOpenTaskHandle extends HandleBase { - AsyncOpenTaskHandle(Pointer pointer) : super(pointer, 32); -} - -class AsyncOpenTaskProgressNotificationTokenHandle extends HandleBase { - AsyncOpenTaskProgressNotificationTokenHandle(Pointer pointer) : super(pointer, 40); -} - extension ListEx on List { Pointer toCharPtr(Allocator allocator) { return toUint8Ptr(allocator).cast(); diff --git a/packages/realm_dart/lib/src/native/results_handle.dart b/packages/realm_dart/lib/src/native/results_handle.dart index 60bac62ea..06de90f62 100644 --- a/packages/realm_dart/lib/src/native/results_handle.dart +++ b/packages/realm_dart/lib/src/native/results_handle.dart @@ -7,6 +7,7 @@ import 'package:ffi/ffi.dart'; import '../realm_dart.dart'; import 'error_handling.dart'; +import 'notification_token_handle.dart'; import 'object_handle.dart'; import 'query_handle.dart'; import 'realm_bindings.dart'; diff --git a/packages/realm_dart/lib/src/native/set_handle.dart b/packages/realm_dart/lib/src/native/set_handle.dart index 668b6255b..406f16fad 100644 --- a/packages/realm_dart/lib/src/native/set_handle.dart +++ b/packages/realm_dart/lib/src/native/set_handle.dart @@ -7,6 +7,7 @@ import 'package:ffi/ffi.dart'; import '../realm_dart.dart'; // TODO: remove this import import 'error_handling.dart'; +import 'notification_token_handle.dart'; import 'query_handle.dart'; import 'realm_bindings.dart'; import 'realm_core.dart'; // TODO: Remove this import diff --git a/packages/realm_dart/lib/src/native/user_handle.dart b/packages/realm_dart/lib/src/native/user_handle.dart index 5dd58fc95..d2b6c0193 100644 --- a/packages/realm_dart/lib/src/native/user_handle.dart +++ b/packages/realm_dart/lib/src/native/user_handle.dart @@ -6,7 +6,6 @@ import 'dart:convert'; import 'dart:ffi'; import 'package:ffi/ffi.dart'; -import 'package:realm_dart/src/app.dart'; import '../credentials.dart'; // TODO: Remove this import import '../realm_dart.dart'; // TODO: Remove this import diff --git a/packages/realm_dart/lib/src/realm_class.dart b/packages/realm_dart/lib/src/realm_class.dart index fb784a4cb..162fcf666 100644 --- a/packages/realm_dart/lib/src/realm_class.dart +++ b/packages/realm_dart/lib/src/realm_class.dart @@ -13,9 +13,11 @@ import 'configuration.dart'; import 'list.dart'; import 'logging.dart'; import 'map.dart'; +import 'native/async_open_task_handle.dart'; import 'native/handle_base.dart'; import 'native/list_handle.dart'; import 'native/map_handle.dart'; +import 'native/notification_token_handle.dart'; import 'native/object_handle.dart'; import 'native/realm_core.dart'; import 'native/realm_handle.dart'; @@ -179,7 +181,7 @@ class Realm implements Finalizable { _ensureDirectory(config); - final asyncOpenHandle = realmCore.createRealmAsyncOpenTask(config); + final asyncOpenHandle = AsyncOpenTaskHandle.from(config); return await CancellableFuture.from(() async { if (cancellationToken != null && cancellationToken.isCancelled) { throw cancellationToken.exception!; @@ -194,12 +196,12 @@ class Realm implements Finalizable { late final RealmHandle realmHandle; try { - realmHandle = await realmCore.openRealmAsync(asyncOpenHandle, cancellationToken); + realmHandle = await asyncOpenHandle.openAsync(cancellationToken); return Realm._(config, realmHandle); } finally { await progressSubscription?.cancel(); } - }, cancellationToken, onCancel: () => realmCore.cancelOpenRealmAsync(asyncOpenHandle)); + }, cancellationToken, onCancel: () => asyncOpenHandle.cancel()); } static RealmHandle _openRealm(Configuration config) { @@ -1048,7 +1050,7 @@ class RealmAsyncOpenProgressNotificationsController implements ProgressNotificat throw RealmStateError("Progress subscription already started."); } - _tokenHandle = realmCore.realmAsyncOpenRegisterAsyncOpenProgressNotifier(_handle, this); + _tokenHandle = _handle.registerProgressNotifier(this); } void _stop() { diff --git a/packages/realm_dart/lib/src/realm_object.dart b/packages/realm_dart/lib/src/realm_object.dart index 99ce7797d..2e43d28d1 100644 --- a/packages/realm_dart/lib/src/realm_object.dart +++ b/packages/realm_dart/lib/src/realm_object.dart @@ -10,8 +10,8 @@ import 'package:realm_common/realm_common.dart'; import 'configuration.dart'; import 'list.dart'; import 'native/handle_base.dart'; +import 'native/notification_token_handle.dart'; import 'native/object_handle.dart'; -import 'native/realm_core.dart'; import 'native/realm_library.dart'; import 'realm_class.dart'; import 'results.dart'; diff --git a/packages/realm_dart/lib/src/results.dart b/packages/realm_dart/lib/src/results.dart index e399b2b80..f4c669f8f 100644 --- a/packages/realm_dart/lib/src/results.dart +++ b/packages/realm_dart/lib/src/results.dart @@ -9,8 +9,8 @@ import 'package:cancellation_token/cancellation_token.dart'; import 'collections.dart'; import 'native/collection_changes_handle.dart'; import 'native/handle_base.dart'; +import 'native/notification_token_handle.dart'; import 'native/object_handle.dart'; -import 'native/realm_core.dart'; import 'native/results_handle.dart'; import 'realm_class.dart'; import 'realm_object.dart'; diff --git a/packages/realm_dart/lib/src/set.dart b/packages/realm_dart/lib/src/set.dart index 422c35dc5..6ac396f32 100644 --- a/packages/realm_dart/lib/src/set.dart +++ b/packages/realm_dart/lib/src/set.dart @@ -10,8 +10,8 @@ import 'package:collection/collection.dart' as collection; import 'native/collection_changes_handle.dart'; import 'native/handle_base.dart'; +import 'native/notification_token_handle.dart'; import 'native/object_handle.dart'; -import 'native/realm_core.dart'; import 'native/set_handle.dart'; import 'realm_class.dart'; import 'realm_object.dart'; From 4e359f3a4e5b424471c944ca437743e044e0e950 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Mon, 6 May 2024 11:18:55 +0200 Subject: [PATCH 60/68] moving guardSynchronousCallback and getApp out of realm_core.dart --- packages/realm_dart/lib/src/app.dart | 2 +- .../realm_dart/lib/src/native/app_handle.dart | 14 +++++++++ .../lib/src/native/config_handle.dart | 16 ++++++++-- .../realm_dart/lib/src/native/realm_core.dart | 29 ------------------- .../lib/src/native/realm_library.dart | 1 + 5 files changed, 30 insertions(+), 32 deletions(-) diff --git a/packages/realm_dart/lib/src/app.dart b/packages/realm_dart/lib/src/app.dart index d7a334335..3e695a645 100644 --- a/packages/realm_dart/lib/src/app.dart +++ b/packages/realm_dart/lib/src/app.dart @@ -164,7 +164,7 @@ class App implements Finalizable { /// on the main isolate. If an App hasn't been already constructed with the same id, will return null. This method is safe to call /// on a background isolate. static App? getById(String id, {Uri? baseUrl}) { - final handle = realmCore.getApp(id, baseUrl?.toString()); + final handle = AppHandle.get(id, baseUrl?.toString()); return handle == null ? null : App._(handle); } diff --git a/packages/realm_dart/lib/src/native/app_handle.dart b/packages/realm_dart/lib/src/native/app_handle.dart index 364bb07d5..8e637c862 100644 --- a/packages/realm_dart/lib/src/native/app_handle.dart +++ b/packages/realm_dart/lib/src/native/app_handle.dart @@ -38,6 +38,20 @@ class AppHandle extends HandleBase { return AppHandle(realmLib.realm_app_create_cached(appConfigHandle.pointer)); } + static AppHandle? get(String id, String? baseUrl) { + return using((arena) { + final outApp = arena>(); + realmLib + .realm_app_get_cached( + id.toCharPtr(arena), + baseUrl == null ? nullptr : baseUrl.toCharPtr(arena), + outApp, + ) + .raiseLastErrorIfFalse(); + return outApp.value.convert(AppHandle.new); + }); + } + UserHandle? get currentUser { return realmLib.realm_app_get_current_user(pointer).convert(UserHandle.new); } diff --git a/packages/realm_dart/lib/src/native/config_handle.dart b/packages/realm_dart/lib/src/native/config_handle.dart index 405e2c0f5..9935e0f8a 100644 --- a/packages/realm_dart/lib/src/native/config_handle.dart +++ b/packages/realm_dart/lib/src/native/config_handle.dart @@ -1,6 +1,7 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 +import 'dart:async'; import 'dart:ffi'; import 'package:ffi/ffi.dart'; @@ -149,7 +150,7 @@ class ConfigHandle extends HandleBase { void _syncAfterResetCallback(Object userdata, Pointer beforeHandle, Pointer afterReference, bool didRecover, Pointer unlockCallbackFunc) { - guardSynchronousCallback(() async { + _guardSynchronousCallback(() async { final syncConfig = userdata as FlexibleSyncConfiguration; final afterResetCallback = didRecover ? syncConfig.clientResetHandler.onAfterRecovery : syncConfig.clientResetHandler.onAfterDiscard; @@ -225,7 +226,7 @@ void _syncErrorHandlerCallback(Object userdata, Pointer sess } void _syncBeforeResetCallback(Object userdata, Pointer realmPtr, Pointer unlockCallbackFunc) { - guardSynchronousCallback(() async { + _guardSynchronousCallback(() async { final syncConfig = userdata as FlexibleSyncConfiguration; var beforeResetCallback = syncConfig.clientResetHandler.onBeforeReset!; @@ -253,3 +254,14 @@ bool _initialDataCallback(Pointer userdata, Pointer realmPtr return false; } + +void _guardSynchronousCallback(FutureOr Function() callback, Pointer unlockCallbackFunc) async { + Pointer userError = nullptr; + try { + await callback(); + } catch (error) { + userError = error.toPersistentHandle(); + } finally { + realmLib.realm_dart_invoke_unlock_callback(userError, unlockCallbackFunc); + } +} diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index b181c942d..b79b1f9e9 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -12,7 +12,6 @@ import 'package:crypto/crypto.dart'; import 'package:ffi/ffi.dart' hide StringUtf8Pointer, StringUtf16Pointer; import 'package:path/path.dart' as path; import 'package:pubspec_parse/pubspec_parse.dart'; -import 'package:realm_dart/src/native/convert.dart'; import '../app.dart'; import '../configuration.dart'; @@ -21,7 +20,6 @@ import '../realm_class.dart'; import '../realm_object.dart'; import '../scheduler.dart'; import '../user.dart'; -import 'app_handle.dart'; import 'collection_changes_handle.dart'; import 'decimal128.dart'; import 'error_handling.dart'; @@ -112,17 +110,6 @@ String getBundleId() { return base64Encode(sha256.convert([...salt, ...utf8.encode(bundleId)]).bytes); } -void guardSynchronousCallback(FutureOr Function() callback, Pointer unlockCallbackFunc) async { - Pointer userError = nullptr; - try { - await callback(); - } catch (error) { - userError = error.toPersistentHandle(); - } finally { - realmLib.realm_dart_invoke_unlock_callback(userError, unlockCallbackFunc); - } -} - void createCollection(Realm realm, RealmValue value, Pointer Function() createList, Pointer Function() createMap) { CollectionHandleBase? collectionHandle; try { @@ -192,8 +179,6 @@ class _RealmCore { // This prevents reentrance if `realmCore` global variable is accessed during _RealmCore construction realmCore = this; - - realmLib.realm_dart_init_debug_logger(); } void loggerAttach() { @@ -235,20 +220,6 @@ class _RealmCore { return realmLib.realm_app_get_default_base_url().cast().toRealmDartString()!; } - AppHandle? getApp(String id, String? baseUrl) { - return using((arena) { - final outApp = arena>(); - realmLib - .realm_app_get_cached( - id.toCharPtr(arena), - baseUrl == null ? nullptr : baseUrl.toCharPtr(arena), - outApp, - ) - .raiseLastErrorIfFalse(); - return outApp.value.convert(AppHandle.new); - }); - } - void clearCachedApps() { realmLib.realm_clear_cached_apps(); } diff --git a/packages/realm_dart/lib/src/native/realm_library.dart b/packages/realm_dart/lib/src/native/realm_library.dart index beb96a051..f747932df 100644 --- a/packages/realm_dart/lib/src/native/realm_library.dart +++ b/packages/realm_dart/lib/src/native/realm_library.dart @@ -19,5 +19,6 @@ final realmLib = () { isFlutterPlatform ? bugInTheSdkMessage : "Did you forget to run `dart run realm_dart install` after upgrading the realm_dart package?"; throw RealmError('Realm SDK package version does not match the native library version ($libraryVersion != $nativeLibraryVersion). $additionMessage'); } + result.realm_dart_init_debug_logger(); return result; }(); From 199663e1a147cc687421ab4705b2a7cfc8766ec1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Mon, 6 May 2024 13:29:04 +0200 Subject: [PATCH 61/68] Split native convertion functions into separate files --- .../realm_dart/lib/src/configuration.dart | 1 + .../realm_dart/lib/src/native/app_handle.dart | 1 + .../src/native/collection_changes_handle.dart | 2 +- .../lib/src/native/config_handle.dart | 2 +- .../lib/src/native/convert_native.dart | 2 + .../lib/src/native/credentials_handle.dart | 2 +- .../realm_dart/lib/src/native/decimal128.dart | 2 +- .../lib/src/native/error_handling.dart | 2 +- .../lib/src/native/from_native.dart | 339 ++++++++++++ .../lib/src/native/list_handle.dart | 1 + .../realm_dart/lib/src/native/map_handle.dart | 1 + .../mutable_subscription_set_handle.dart | 2 +- .../lib/src/native/object_handle.dart | 1 + .../realm_dart/lib/src/native/realm_core.dart | 490 +----------------- .../lib/src/native/realm_handle.dart | 2 +- .../lib/src/native/results_handle.dart | 1 + .../lib/src/native/schema_handle.dart | 3 +- .../lib/src/native/session_handle.dart | 3 +- .../realm_dart/lib/src/native/set_handle.dart | 1 + .../lib/src/native/subscription_handle.dart | 2 +- .../src/native/subscription_set_handle.dart | 4 +- .../realm_dart/lib/src/native/to_native.dart | 172 ++++++ .../lib/src/native/user_handle.dart | 2 +- 23 files changed, 536 insertions(+), 502 deletions(-) create mode 100644 packages/realm_dart/lib/src/native/convert_native.dart create mode 100644 packages/realm_dart/lib/src/native/from_native.dart create mode 100644 packages/realm_dart/lib/src/native/to_native.dart diff --git a/packages/realm_dart/lib/src/configuration.dart b/packages/realm_dart/lib/src/configuration.dart index c05d8bb20..4d02b5adc 100644 --- a/packages/realm_dart/lib/src/configuration.dart +++ b/packages/realm_dart/lib/src/configuration.dart @@ -11,6 +11,7 @@ import 'package:path/path.dart' as _path; import 'app.dart'; import 'init.dart'; import 'logging.dart'; +import 'native/from_native.dart'; import 'native/realm_core.dart'; import 'realm_class.dart'; import 'user.dart'; diff --git a/packages/realm_dart/lib/src/native/app_handle.dart b/packages/realm_dart/lib/src/native/app_handle.dart index 8e637c862..6417ede86 100644 --- a/packages/realm_dart/lib/src/native/app_handle.dart +++ b/packages/realm_dart/lib/src/native/app_handle.dart @@ -14,6 +14,7 @@ import '../logging.dart'; import '../realm_class.dart'; // TODO: Remove this import import '../scheduler.dart'; import 'convert.dart'; +import 'convert_native.dart'; import 'credentials_handle.dart'; import 'error_handling.dart'; import 'handle_base.dart'; diff --git a/packages/realm_dart/lib/src/native/collection_changes_handle.dart b/packages/realm_dart/lib/src/native/collection_changes_handle.dart index d5df9a5ec..9d9f4d594 100644 --- a/packages/realm_dart/lib/src/native/collection_changes_handle.dart +++ b/packages/realm_dart/lib/src/native/collection_changes_handle.dart @@ -6,9 +6,9 @@ import 'dart:ffi'; import 'package:ffi/ffi.dart'; import '../collections.dart'; // TODO: Remove this import +import 'from_native.dart'; import 'handle_base.dart'; import 'realm_bindings.dart'; -import 'realm_core.dart'; // TODO: Remove this import import 'realm_library.dart'; class CollectionChangesHandle extends HandleBase { diff --git a/packages/realm_dart/lib/src/native/config_handle.dart b/packages/realm_dart/lib/src/native/config_handle.dart index 9935e0f8a..d23c08727 100644 --- a/packages/realm_dart/lib/src/native/config_handle.dart +++ b/packages/realm_dart/lib/src/native/config_handle.dart @@ -12,9 +12,9 @@ import '../migration.dart'; // TODO: Remove this import import '../realm_class.dart'; // TODO: Remove this import import '../scheduler.dart'; // TODO: Remove this import import '../user.dart'; // TODO: Remove this import +import 'convert_native.dart'; import 'handle_base.dart'; import 'realm_bindings.dart'; -import 'realm_core.dart'; import 'realm_handle.dart'; import 'realm_library.dart'; import 'schema_handle.dart'; // TODO: Remove this import diff --git a/packages/realm_dart/lib/src/native/convert_native.dart b/packages/realm_dart/lib/src/native/convert_native.dart new file mode 100644 index 000000000..6f7cb2aaf --- /dev/null +++ b/packages/realm_dart/lib/src/native/convert_native.dart @@ -0,0 +1,2 @@ +export 'to_native.dart'; +export 'from_native.dart'; diff --git a/packages/realm_dart/lib/src/native/credentials_handle.dart b/packages/realm_dart/lib/src/native/credentials_handle.dart index 5f7f1811b..fe31acd39 100644 --- a/packages/realm_dart/lib/src/native/credentials_handle.dart +++ b/packages/realm_dart/lib/src/native/credentials_handle.dart @@ -8,8 +8,8 @@ import 'package:ffi/ffi.dart'; import '../credentials.dart'; // TODO: Remove this import import 'handle_base.dart'; import 'realm_bindings.dart'; -import 'realm_core.dart'; // TODO: Remove this import import 'realm_library.dart'; +import 'to_native.dart'; class CredentialsHandle extends HandleBase { CredentialsHandle(Pointer pointer) : super(pointer, 16); diff --git a/packages/realm_dart/lib/src/native/decimal128.dart b/packages/realm_dart/lib/src/native/decimal128.dart index 24fca8d6f..157c4780e 100644 --- a/packages/realm_dart/lib/src/native/decimal128.dart +++ b/packages/realm_dart/lib/src/native/decimal128.dart @@ -8,8 +8,8 @@ import 'package:ffi/ffi.dart'; import 'package:realm_common/realm_common.dart' as common; import 'realm_bindings.dart'; -import 'realm_core.dart'; // TODO: Remove this import import 'realm_library.dart'; +import 'to_native.dart'; /// A 128-bit decimal floating point number. class Decimal128 implements Comparable, common.Decimal128 { diff --git a/packages/realm_dart/lib/src/native/error_handling.dart b/packages/realm_dart/lib/src/native/error_handling.dart index 1faae1930..5aeae56ef 100644 --- a/packages/realm_dart/lib/src/native/error_handling.dart +++ b/packages/realm_dart/lib/src/native/error_handling.dart @@ -6,8 +6,8 @@ import 'dart:ffi'; import 'package:ffi/ffi.dart'; import '../realm_object.dart'; // TODO: Remove this import +import 'from_native.dart'; import 'realm_bindings.dart'; -import 'realm_core.dart'; import 'realm_library.dart'; extension PointerEx on Pointer { diff --git a/packages/realm_dart/lib/src/native/from_native.dart b/packages/realm_dart/lib/src/native/from_native.dart new file mode 100644 index 000000000..bd218a9b2 --- /dev/null +++ b/packages/realm_dart/lib/src/native/from_native.dart @@ -0,0 +1,339 @@ +import 'dart:async'; +import 'dart:ffi'; +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:ffi/ffi.dart'; + +import '../app.dart'; +import '../configuration.dart'; +import '../realm_class.dart'; +import '../user.dart'; +import 'decimal128.dart'; +import 'list_handle.dart'; +import 'map_handle.dart'; +import 'realm_bindings.dart'; +import 'realm_library.dart'; + +// TODO: Duplicated in to_native.dart +const int _microsecondsPerSecond = 1000 * 1000; +const int _nanosecondsPerMicrosecond = 1000; + +extension RealmValueEx on realm_value_t { + Object? toPrimitiveValue() => toDartValue(realm: null, getList: null, getMap: null); + + Object? toDartValue({required Realm? realm, required Pointer Function()? getList, required Pointer Function()? getMap}) { + switch (type) { + case realm_value_type.RLM_TYPE_NULL: + return null; + case realm_value_type.RLM_TYPE_INT: + return values.integer; + case realm_value_type.RLM_TYPE_BOOL: + return values.boolean; + case realm_value_type.RLM_TYPE_STRING: + return values.string.data.cast().toRealmDartString(length: values.string.size)!; + case realm_value_type.RLM_TYPE_FLOAT: + return values.fnum; + case realm_value_type.RLM_TYPE_DOUBLE: + return values.dnum; + case realm_value_type.RLM_TYPE_LINK: + if (realm == null) { + throw RealmError("A realm instance is required to resolve Backlinks"); + } + final objectKey = values.link.target; + final classKey = values.link.target_table; + if (realm.metadata.getByClassKeyIfExists(classKey) == null) return null; // temporary workaround to avoid crash on assertion + return realm.handle.getObject(classKey, objectKey); + case realm_value_type.RLM_TYPE_BINARY: + return Uint8List.fromList(values.binary.data.asTypedList(values.binary.size)); + case realm_value_type.RLM_TYPE_TIMESTAMP: + final seconds = values.timestamp.seconds; + final nanoseconds = values.timestamp.nanoseconds; + return DateTime.fromMicrosecondsSinceEpoch(seconds * _microsecondsPerSecond + nanoseconds ~/ _nanosecondsPerMicrosecond, isUtc: true); + case realm_value_type.RLM_TYPE_DECIMAL128: + var decimal = values.decimal128; // NOTE: Does not copy the struct! + decimal = realmLib.realm_dart_decimal128_copy(decimal); // This is a workaround to that + return Decimal128Internal.fromNative(decimal); + case realm_value_type.RLM_TYPE_OBJECT_ID: + return ObjectId.fromBytes(values.object_id.bytes.toList(12)); + case realm_value_type.RLM_TYPE_UUID: + final listInt = values.uuid.bytes.toList(16); + return Uuid.fromBytes(Uint8List.fromList(listInt).buffer); + case realm_value_type.RLM_TYPE_LIST: + if (getList == null || realm == null) { + throw RealmException('toDartValue called with a list argument but without a list getter'); + } + + final listHandle = ListHandle(getList(), realm.handle); + return realm.createList(listHandle, null); + case realm_value_type.RLM_TYPE_DICTIONARY: + if (getMap == null || realm == null) { + throw RealmException('toDartValue called with a list argument but without a list getter'); + } + + final mapHandle = MapHandle(getMap(), realm.handle); + return realm.createMap(mapHandle, null); + default: + throw RealmException("realm_value_type $type not supported"); + } + } +} + +extension ArrayUint8Ex on Array { + List toList(int count) { + final result = []; + for (var i = 0; i < count; i++) { + result.add(this[i]); + } + return result; + } +} + +extension PointerSizeEx on Pointer { + List toIntList(int count) { + List result = List.filled(count, value); + for (var i = 1; i < count; i++) { + result[i] = (this + i).value; + } + return result; + } +} + +extension PointerVoidEx on Pointer { + T toObject() { + assert(this != nullptr, "Pointer is null"); + + Object object = realmLib.realm_dart_persistent_handle_to_object(this); + + assert(object is T, "$T expected"); + return object as T; + } + + Object? toUserCodeError() { + if (this != nullptr) { + final result = toObject(); + realmLib.realm_dart_delete_persistent_handle(this); + return result; + } + + return null; + } +} + +extension PointerUtf8Ex on Pointer { + String? toRealmDartString({bool treatEmptyAsNull = false, int? length, bool freeRealmMemory = false}) { + if (this == nullptr) { + return null; + } + + try { + final result = toDartString(length: length); + + if (treatEmptyAsNull && result == '') { + return null; + } + return result; + } finally { + if (freeRealmMemory) { + realmLib.realm_free(cast()); + } + } + } +} + +extension RealmSyncErrorEx on realm_sync_error { + SyncErrorDetails toDart() { + final message = status.message.cast().toRealmDartString()!; + final userInfoMap = user_info_map.toDart(user_info_length); + final originalFilePathKey = c_original_file_path_key.cast().toRealmDartString(); + final recoveryFilePathKey = c_recovery_file_path_key.cast().toRealmDartString(); + + return SyncErrorDetails( + message, + status.error, + user_code_error.toUserCodeError(), + isFatal: is_fatal, + isClientResetRequested: is_client_reset_requested, + originalFilePath: userInfoMap?[originalFilePathKey], + backupFilePath: userInfoMap?[recoveryFilePathKey], + compensatingWrites: compensating_writes.toList(compensating_writes_length), + ); + } +} + +extension PointerRealmSyncErrorUserInfoEx on Pointer { + Map? toDart(int length) { + if (this == nullptr) { + return null; + } + Map userInfoMap = {}; + for (int i = 0; i < length; i++) { + final userInfoItem = this[i]; + final key = userInfoItem.key.cast().toDartString(); + final value = userInfoItem.value.cast().toDartString(); + userInfoMap[key] = value; + } + return userInfoMap; + } +} + +extension PointerRealmSyncErrorCompensatingWriteInfoEx on Pointer { + List? toList(int length) { + if (this == nullptr || length == 0) { + return null; + } + List compensatingWrites = []; + for (int i = 0; i < length; i++) { + final compensatingWrite = this[i]; + final reason = compensatingWrite.reason.cast().toDartString(); + final objectName = compensatingWrite.object_name.cast().toDartString(); + final primaryKey = compensatingWrite.primary_key.toPrimitiveValue(); + compensatingWrites.add(CompensatingWriteInfo(objectName, reason, RealmValue.from(primaryKey))); + } + return compensatingWrites; + } +} + +extension PointerRealmErrorEx on Pointer { + SyncError toDart() { + final message = ref.message.cast().toDartString(); + final details = SyncErrorDetails(message, ref.error, ref.user_code_error.toUserCodeError()); + return SyncErrorInternal.createSyncError(details); + } +} + +extension ObjectEx on Object { + Pointer toPersistentHandle() { + return realmLib.realm_dart_object_to_persistent_handle(this); + } +} + +extension ListUserStateEx on List { + UserState fromIndex(int index) { + if (!UserState.values.any((value) => value.index == index)) { + throw RealmError("Unknown user state $index"); + } + + return UserState.values[index]; + } +} + +extension RealmPropertyInfoEx on realm_property_info { + SchemaProperty toSchemaProperty() { + final linkTarget = link_target == nullptr ? null : link_target.cast().toDartString(); + return SchemaProperty(name.cast().toDartString(), RealmPropertyType.values[type], + optional: flags & realm_property_flags.RLM_PROPERTY_NULLABLE == realm_property_flags.RLM_PROPERTY_NULLABLE, + primaryKey: flags & realm_property_flags.RLM_PROPERTY_PRIMARY_KEY == realm_property_flags.RLM_PROPERTY_PRIMARY_KEY, + linkTarget: linkTarget == null || linkTarget.isEmpty ? null : linkTarget, + collectionType: RealmCollectionType.values[collection_type]); + } +} + +extension CompleterEx on Completer { + void completeFrom(FutureOr Function() action) { + try { + complete(action()); + } catch (error, stackTrace) { + completeError(error, stackTrace); + } + } + + void completeWithAppError(Pointer error) { + final message = error.ref.message.cast().toRealmDartString()!; + final linkToLogs = error.ref.link_to_server_logs.cast().toRealmDartString(); + completeError(AppInternal.createException(message, linkToLogs, error.ref.http_status_code)); + } +} + +enum CustomErrorCode { + noError(0), + unknownHttp(998), + unknown(999), + timeout(1000); + + final int code; + const CustomErrorCode(this.code); +} + +enum HttpMethod { + get, + post, + patch, + put, + delete, +} + +extension RealmTimestampEx on realm_timestamp_t { + DateTime toDart() { + return DateTime.fromMicrosecondsSinceEpoch(seconds * 1000000 + nanoseconds ~/ 1000, isUtc: true); + } +} + +extension RealmStringEx on realm_string_t { + String? toDart() => data.cast().toRealmDartString(); +} + +extension ObjectIdEx on ObjectId { + Pointer toNative(Allocator allocator) { + final result = allocator(); + for (var i = 0; i < 12; i++) { + result.ref.bytes[i] = bytes[i]; + } + return result; + } +} + +extension RealmObjectIdEx on realm_object_id { + ObjectId toDart() { + final buffer = Uint8List(12); + for (int i = 0; i < 12; ++i) { + buffer[i] = bytes[i]; + } + return ObjectId.fromBytes(buffer); + } +} + +extension RealmAppUserApikeyEx on realm_app_user_apikey { + ApiKey toDart() => UserInternal.createApiKey( + id.toDart(), + name.cast().toDartString(), + key.cast().toRealmDartString(treatEmptyAsNull: true), + !disabled, + ); +} + +extension PlatformEx on Platform { + static String fromEnvironment(String name, {String defaultValue = ""}) { + final result = Platform.environment[name]; + if (result == null) { + return defaultValue; + } + + return result; + } +} + +/// @nodoc +class SyncErrorDetails { + final String message; + final int code; + final String? path; + final bool isFatal; + final bool isClientResetRequested; + final String? originalFilePath; + final String? backupFilePath; + final List? compensatingWrites; + final Object? userError; + + SyncErrorDetails( + this.message, + this.code, + this.userError, { + this.path, + this.isFatal = false, + this.isClientResetRequested = false, + this.originalFilePath, + this.backupFilePath, + this.compensatingWrites, + }); +} diff --git a/packages/realm_dart/lib/src/native/list_handle.dart b/packages/realm_dart/lib/src/native/list_handle.dart index b8f12ee1e..cf7640600 100644 --- a/packages/realm_dart/lib/src/native/list_handle.dart +++ b/packages/realm_dart/lib/src/native/list_handle.dart @@ -6,6 +6,7 @@ import 'dart:ffi'; import 'package:ffi/ffi.dart'; import '../realm_dart.dart'; +import 'convert_native.dart'; import 'error_handling.dart'; import 'notification_token_handle.dart'; import 'object_handle.dart'; diff --git a/packages/realm_dart/lib/src/native/map_handle.dart b/packages/realm_dart/lib/src/native/map_handle.dart index c974d3553..6eb5883d2 100644 --- a/packages/realm_dart/lib/src/native/map_handle.dart +++ b/packages/realm_dart/lib/src/native/map_handle.dart @@ -6,6 +6,7 @@ import 'dart:ffi'; import 'package:ffi/ffi.dart'; import '../realm_dart.dart'; // TODO: remove this import +import 'convert_native.dart'; import 'error_handling.dart'; import 'map_changes_handle.dart'; import 'notification_token_handle.dart'; diff --git a/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart b/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart index f48b1288c..1f33e28cd 100644 --- a/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart +++ b/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart @@ -6,9 +6,9 @@ import 'dart:ffi'; import 'package:ffi/ffi.dart'; import '../realm_dart.dart'; // TODO: Remove this import +import 'convert_native.dart'; import 'error_handling.dart'; import 'realm_bindings.dart'; -import 'realm_core.dart'; // TODO: Remove this import import 'realm_handle.dart'; import 'realm_library.dart'; import 'results_handle.dart'; diff --git a/packages/realm_dart/lib/src/native/object_handle.dart b/packages/realm_dart/lib/src/native/object_handle.dart index a5bcefc3e..741f5421e 100644 --- a/packages/realm_dart/lib/src/native/object_handle.dart +++ b/packages/realm_dart/lib/src/native/object_handle.dart @@ -6,6 +6,7 @@ import 'dart:ffi'; import 'package:ffi/ffi.dart'; import '../realm_dart.dart'; // TODO: Remove this import +import 'convert_native.dart'; import 'error_handling.dart'; import 'handle_base.dart'; import 'list_handle.dart'; diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index b79b1f9e9..ba644848c 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -1,11 +1,9 @@ // Copyright 2021 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -import 'dart:async'; import 'dart:convert'; import 'dart:ffi'; import 'dart:io'; -import 'dart:typed_data'; import 'package:crypto/crypto.dart'; // Hide StringUtf8Pointer.toNativeUtf8 and StringUtf16Pointer since these allows silently allocating memory. Use toUtf8Ptr instead @@ -13,15 +11,11 @@ import 'package:ffi/ffi.dart' hide StringUtf8Pointer, StringUtf16Pointer; import 'package:path/path.dart' as path; import 'package:pubspec_parse/pubspec_parse.dart'; -import '../app.dart'; -import '../configuration.dart'; import '../init.dart'; import '../realm_class.dart'; -import '../realm_object.dart'; import '../scheduler.dart'; -import '../user.dart'; import 'collection_changes_handle.dart'; -import 'decimal128.dart'; +import 'convert_native.dart'; import 'error_handling.dart'; import 'list_handle.dart'; import 'map_handle.dart'; @@ -281,150 +275,6 @@ class _RealmCore { } } -extension ListEx on List { - Pointer toCharPtr(Allocator allocator) { - return toUint8Ptr(allocator).cast(); - } - - Pointer toUint8Ptr(Allocator allocator) { - final nativeSize = length + 1; - final result = allocator(nativeSize); - final Uint8List native = result.asTypedList(nativeSize); - native.setAll(0, this); // copy - native.last = 0; // zero terminate - return result.cast(); - } -} - -extension StringEx on String { - Pointer toCharPtr(Allocator allocator) { - final units = utf8.encode(this); - return units.toCharPtr(allocator).cast(); - } - - Pointer toRealmString(Allocator allocator) { - final realmString = allocator(); - final units = utf8.encode(this); - realmString.ref.data = units.toCharPtr(allocator).cast(); - realmString.ref.size = units.length; - return realmString; - } -} - -extension NullableObjectEx on Object? { - Pointer toNative(Allocator allocator) { - final self = this; - final realmValue = allocator(); - if (self is RealmValue && self.type.isCollection) { - throw RealmError( - "Don't use _toPrimitiveValue if the value may contain collections. Use storeValue instead. This is a bug in the Realm Flutter SDK and should be reported to https://github.com/realm/realm-dart/issues/new"); - } - _intoRealmValue(self, realmValue.ref, allocator); - return realmValue; - } -} - -const int _microsecondsPerSecond = 1000 * 1000; -const int _nanosecondsPerMicrosecond = 1000; - -void intoRealmQueryArg(Object? value, Pointer realmQueryArg, Allocator allocator) { - if (value is Iterable) { - realmQueryArg.ref.nb_args = value.length; - realmQueryArg.ref.is_list = true; - realmQueryArg.ref.arg = allocator(value.length); - int i = 0; - for (var item in value) { - _intoRealmValue(item, realmQueryArg.ref.arg[i], allocator); - i++; - } - } else { - realmQueryArg.ref.arg = allocator(); - realmQueryArg.ref.nb_args = 1; - realmQueryArg.ref.is_list = false; - _intoRealmValueHack(value, realmQueryArg.ref.arg.ref, allocator); - } -} - -void _intoRealmValueHack(Object? value, realm_value realmValue, Allocator allocator) { - if (value is GeoShape) { - _intoRealmValue(value.toString(), realmValue, allocator); - } else if (value is RealmValueType) { - _intoRealmValue(value.toQueryArgString(), realmValue, allocator); - } else { - _intoRealmValue(value, realmValue, allocator); - } -} - -void _intoRealmValue(Object? value, realm_value realmValue, Allocator allocator) { - if (value == null) { - realmValue.type = realm_value_type.RLM_TYPE_NULL; - } else if (value is RealmObjectBase) { - // when converting a RealmObjectBase to realm_value.link we assume the object is managed - final link = value.handle.asLink; - realmValue.values.link.target = link.targetKey; - realmValue.values.link.target_table = link.classKey; - realmValue.type = realm_value_type.RLM_TYPE_LINK; - } else if (value is int) { - realmValue.values.integer = value; - realmValue.type = realm_value_type.RLM_TYPE_INT; - } else if (value is bool) { - realmValue.values.boolean = value; - realmValue.type = realm_value_type.RLM_TYPE_BOOL; - } else if (value is String) { - String string = value; - final units = utf8.encode(string); - final result = allocator(units.length); - final Uint8List nativeString = result.asTypedList(units.length); - nativeString.setAll(0, units); - realmValue.values.string.data = result.cast(); - realmValue.values.string.size = units.length; - realmValue.type = realm_value_type.RLM_TYPE_STRING; - } else if (value is double) { - realmValue.values.dnum = value; - realmValue.type = realm_value_type.RLM_TYPE_DOUBLE; - } else if (value is ObjectId) { - final bytes = value.bytes; - for (var i = 0; i < 12; i++) { - realmValue.values.object_id.bytes[i] = bytes[i]; - } - realmValue.type = realm_value_type.RLM_TYPE_OBJECT_ID; - } else if (value is Uuid) { - final bytes = value.bytes.asUint8List(); - for (var i = 0; i < 16; i++) { - realmValue.values.uuid.bytes[i] = bytes[i]; - } - realmValue.type = realm_value_type.RLM_TYPE_UUID; - } else if (value is DateTime) { - final microseconds = value.toUtc().microsecondsSinceEpoch; - final seconds = microseconds ~/ _microsecondsPerSecond; - int nanoseconds = _nanosecondsPerMicrosecond * (microseconds % _microsecondsPerSecond); - if (microseconds < 0 && nanoseconds != 0) { - nanoseconds = nanoseconds - _nanosecondsPerMicrosecond * _microsecondsPerSecond; - } - realmValue.values.timestamp.seconds = seconds; - realmValue.values.timestamp.nanoseconds = nanoseconds; - realmValue.type = realm_value_type.RLM_TYPE_TIMESTAMP; - } else if (value is Decimal128) { - realmValue.values.decimal128 = value.value; - realmValue.type = realm_value_type.RLM_TYPE_DECIMAL128; - } else if (value is Uint8List) { - realmValue.type = realm_value_type.RLM_TYPE_BINARY; - realmValue.values.binary.size = value.length; - realmValue.values.binary.data = allocator(value.length); - realmValue.values.binary.data.asTypedList(value.length).setAll(0, value); - } else if (value is RealmValue) { - if (value is List) { - realmValue.type = realm_value_type.RLM_TYPE_LIST; - } else if (value is Map) { - realmValue.type = realm_value_type.RLM_TYPE_DICTIONARY; - } else { - return _intoRealmValue(value.value, realmValue, allocator); - } - } else { - throw RealmException("Property type ${value.runtimeType} not supported"); - } -} - extension PointerRealmValueEx on Pointer { Object? toDartValue(Realm realm, Pointer Function()? getList, Pointer Function()? getMap) { if (this == nullptr) { @@ -444,341 +294,3 @@ extension PointerRealmValueEx on Pointer { } } -extension RealmValueEx on realm_value_t { - Object? toPrimitiveValue() => toDartValue(realm: null, getList: null, getMap: null); - - Object? toDartValue({required Realm? realm, required Pointer Function()? getList, required Pointer Function()? getMap}) { - switch (type) { - case realm_value_type.RLM_TYPE_NULL: - return null; - case realm_value_type.RLM_TYPE_INT: - return values.integer; - case realm_value_type.RLM_TYPE_BOOL: - return values.boolean; - case realm_value_type.RLM_TYPE_STRING: - return values.string.data.cast().toRealmDartString(length: values.string.size)!; - case realm_value_type.RLM_TYPE_FLOAT: - return values.fnum; - case realm_value_type.RLM_TYPE_DOUBLE: - return values.dnum; - case realm_value_type.RLM_TYPE_LINK: - if (realm == null) { - throw RealmError("A realm instance is required to resolve Backlinks"); - } - final objectKey = values.link.target; - final classKey = values.link.target_table; - if (realm.metadata.getByClassKeyIfExists(classKey) == null) return null; // temporary workaround to avoid crash on assertion - return realm.handle.getObject(classKey, objectKey); - case realm_value_type.RLM_TYPE_BINARY: - return Uint8List.fromList(values.binary.data.asTypedList(values.binary.size)); - case realm_value_type.RLM_TYPE_TIMESTAMP: - final seconds = values.timestamp.seconds; - final nanoseconds = values.timestamp.nanoseconds; - return DateTime.fromMicrosecondsSinceEpoch(seconds * _microsecondsPerSecond + nanoseconds ~/ _nanosecondsPerMicrosecond, isUtc: true); - case realm_value_type.RLM_TYPE_DECIMAL128: - var decimal = values.decimal128; // NOTE: Does not copy the struct! - decimal = realmLib.realm_dart_decimal128_copy(decimal); // This is a workaround to that - return Decimal128Internal.fromNative(decimal); - case realm_value_type.RLM_TYPE_OBJECT_ID: - return ObjectId.fromBytes(values.object_id.bytes.toList(12)); - case realm_value_type.RLM_TYPE_UUID: - final listInt = values.uuid.bytes.toList(16); - return Uuid.fromBytes(Uint8List.fromList(listInt).buffer); - case realm_value_type.RLM_TYPE_LIST: - if (getList == null || realm == null) { - throw RealmException('toDartValue called with a list argument but without a list getter'); - } - - final listHandle = ListHandle(getList(), realm.handle); - return realm.createList(listHandle, null); - case realm_value_type.RLM_TYPE_DICTIONARY: - if (getMap == null || realm == null) { - throw RealmException('toDartValue called with a list argument but without a list getter'); - } - - final mapHandle = MapHandle(getMap(), realm.handle); - return realm.createMap(mapHandle, null); - default: - throw RealmException("realm_value_type $type not supported"); - } - } -} - -extension ArrayUint8Ex on Array { - List toList(int count) { - final result = []; - for (var i = 0; i < count; i++) { - result.add(this[i]); - } - return result; - } -} - -extension PointerSizeEx on Pointer { - List toIntList(int count) { - List result = List.filled(count, value); - for (var i = 1; i < count; i++) { - result[i] = (this + i).value; - } - return result; - } -} - -extension PointerVoidEx on Pointer { - T toObject() { - assert(this != nullptr, "Pointer is null"); - - Object object = realmLib.realm_dart_persistent_handle_to_object(this); - - assert(object is T, "$T expected"); - return object as T; - } - - Object? toUserCodeError() { - if (this != nullptr) { - final result = toObject(); - realmLib.realm_dart_delete_persistent_handle(this); - return result; - } - - return null; - } -} - -extension PointerUtf8Ex on Pointer { - String? toRealmDartString({bool treatEmptyAsNull = false, int? length, bool freeRealmMemory = false}) { - if (this == nullptr) { - return null; - } - - try { - final result = toDartString(length: length); - - if (treatEmptyAsNull && result == '') { - return null; - } - return result; - } finally { - if (freeRealmMemory) { - realmLib.realm_free(cast()); - } - } - } -} - -extension RealmSyncErrorEx on realm_sync_error { - SyncErrorDetails toDart() { - final message = status.message.cast().toRealmDartString()!; - final userInfoMap = user_info_map.toDart(user_info_length); - final originalFilePathKey = c_original_file_path_key.cast().toRealmDartString(); - final recoveryFilePathKey = c_recovery_file_path_key.cast().toRealmDartString(); - - return SyncErrorDetails( - message, - status.error, - user_code_error.toUserCodeError(), - isFatal: is_fatal, - isClientResetRequested: is_client_reset_requested, - originalFilePath: userInfoMap?[originalFilePathKey], - backupFilePath: userInfoMap?[recoveryFilePathKey], - compensatingWrites: compensating_writes.toList(compensating_writes_length), - ); - } -} - -extension PointerRealmSyncErrorUserInfoEx on Pointer { - Map? toDart(int length) { - if (this == nullptr) { - return null; - } - Map userInfoMap = {}; - for (int i = 0; i < length; i++) { - final userInfoItem = this[i]; - final key = userInfoItem.key.cast().toDartString(); - final value = userInfoItem.value.cast().toDartString(); - userInfoMap[key] = value; - } - return userInfoMap; - } -} - -extension PointerRealmSyncErrorCompensatingWriteInfoEx on Pointer { - List? toList(int length) { - if (this == nullptr || length == 0) { - return null; - } - List compensatingWrites = []; - for (int i = 0; i < length; i++) { - final compensatingWrite = this[i]; - final reason = compensatingWrite.reason.cast().toDartString(); - final objectName = compensatingWrite.object_name.cast().toDartString(); - final primaryKey = compensatingWrite.primary_key.toPrimitiveValue(); - compensatingWrites.add(CompensatingWriteInfo(objectName, reason, RealmValue.from(primaryKey))); - } - return compensatingWrites; - } -} - -extension PointerRealmErrorEx on Pointer { - SyncError toDart() { - final message = ref.message.cast().toDartString(); - final details = SyncErrorDetails(message, ref.error, ref.user_code_error.toUserCodeError()); - return SyncErrorInternal.createSyncError(details); - } -} - -extension ObjectEx on Object { - Pointer toPersistentHandle() { - return realmLib.realm_dart_object_to_persistent_handle(this); - } -} - -extension ListUserStateEx on List { - UserState fromIndex(int index) { - if (!UserState.values.any((value) => value.index == index)) { - throw RealmError("Unknown user state $index"); - } - - return UserState.values[index]; - } -} - -extension RealmPropertyInfoEx on realm_property_info { - SchemaProperty toSchemaProperty() { - final linkTarget = link_target == nullptr ? null : link_target.cast().toDartString(); - return SchemaProperty(name.cast().toDartString(), RealmPropertyType.values[type], - optional: flags & realm_property_flags.RLM_PROPERTY_NULLABLE == realm_property_flags.RLM_PROPERTY_NULLABLE, - primaryKey: flags & realm_property_flags.RLM_PROPERTY_PRIMARY_KEY == realm_property_flags.RLM_PROPERTY_PRIMARY_KEY, - linkTarget: linkTarget == null || linkTarget.isEmpty ? null : linkTarget, - collectionType: RealmCollectionType.values[collection_type]); - } -} - -extension CompleterEx on Completer { - void completeFrom(FutureOr Function() action) { - try { - complete(action()); - } catch (error, stackTrace) { - completeError(error, stackTrace); - } - } - - void completeWithAppError(Pointer error) { - final message = error.ref.message.cast().toRealmDartString()!; - final linkToLogs = error.ref.link_to_server_logs.cast().toRealmDartString(); - completeError(AppInternal.createException(message, linkToLogs, error.ref.http_status_code)); - } -} - -enum CustomErrorCode { - noError(0), - unknownHttp(998), - unknown(999), - timeout(1000); - - final int code; - const CustomErrorCode(this.code); -} - -enum HttpMethod { - get, - post, - patch, - put, - delete, -} - -extension RealmTimestampEx on realm_timestamp_t { - DateTime toDart() { - return DateTime.fromMicrosecondsSinceEpoch(seconds * 1000000 + nanoseconds ~/ 1000, isUtc: true); - } -} - -extension RealmStringEx on realm_string_t { - String? toDart() => data.cast().toRealmDartString(); -} - -extension ObjectIdEx on ObjectId { - Pointer toNative(Allocator allocator) { - final result = allocator(); - for (var i = 0; i < 12; i++) { - result.ref.bytes[i] = bytes[i]; - } - return result; - } -} - -extension RealmObjectIdEx on realm_object_id { - ObjectId toDart() { - final buffer = Uint8List(12); - for (int i = 0; i < 12; ++i) { - buffer[i] = bytes[i]; - } - return ObjectId.fromBytes(buffer); - } -} - -extension RealmAppUserApikeyEx on realm_app_user_apikey { - ApiKey toDart() => UserInternal.createApiKey( - id.toDart(), - name.cast().toDartString(), - key.cast().toRealmDartString(treatEmptyAsNull: true), - !disabled, - ); -} - -extension PlatformEx on Platform { - static String fromEnvironment(String name, {String defaultValue = ""}) { - final result = Platform.environment[name]; - if (result == null) { - return defaultValue; - } - - return result; - } -} - -/// @nodoc -class SyncErrorDetails { - final String message; - final int code; - final String? path; - final bool isFatal; - final bool isClientResetRequested; - final String? originalFilePath; - final String? backupFilePath; - final List? compensatingWrites; - final Object? userError; - - SyncErrorDetails( - this.message, - this.code, - this.userError, { - this.path, - this.isFatal = false, - this.isClientResetRequested = false, - this.originalFilePath, - this.backupFilePath, - this.compensatingWrites, - }); -} - -extension RealmValueTypeEx on RealmValueType { - String toQueryArgString() { - return switch (this) { - RealmValueType.nullValue => 'null', - RealmValueType.boolean => 'bool', - RealmValueType.string => 'string', - RealmValueType.int => 'int', - RealmValueType.double => 'double', - RealmValueType.object => 'link', - RealmValueType.objectId => 'objectid', - RealmValueType.dateTime => 'date', - RealmValueType.decimal => 'decimal', - RealmValueType.uuid => 'uuid', - RealmValueType.binary => 'binary', - RealmValueType.list => 'array', - RealmValueType.map => 'object', - }; - } -} diff --git a/packages/realm_dart/lib/src/native/realm_handle.dart b/packages/realm_dart/lib/src/native/realm_handle.dart index 1e7e0bd9f..9e6931325 100644 --- a/packages/realm_dart/lib/src/native/realm_handle.dart +++ b/packages/realm_dart/lib/src/native/realm_handle.dart @@ -12,12 +12,12 @@ import '../logging.dart'; import '../realm_class.dart'; import '../realm_object.dart'; import 'config_handle.dart'; +import 'convert_native.dart'; import 'error_handling.dart'; import 'handle_base.dart'; import 'object_handle.dart'; import 'query_handle.dart'; import 'realm_bindings.dart'; -import 'realm_core.dart'; import 'realm_library.dart'; import 'results_handle.dart'; import 'rooted_handle.dart'; diff --git a/packages/realm_dart/lib/src/native/results_handle.dart b/packages/realm_dart/lib/src/native/results_handle.dart index 06de90f62..9d85ed071 100644 --- a/packages/realm_dart/lib/src/native/results_handle.dart +++ b/packages/realm_dart/lib/src/native/results_handle.dart @@ -6,6 +6,7 @@ import 'dart:ffi'; import 'package:ffi/ffi.dart'; import '../realm_dart.dart'; +import 'convert_native.dart'; import 'error_handling.dart'; import 'notification_token_handle.dart'; import 'object_handle.dart'; diff --git a/packages/realm_dart/lib/src/native/schema_handle.dart b/packages/realm_dart/lib/src/native/schema_handle.dart index 588d0496f..4eb37873f 100644 --- a/packages/realm_dart/lib/src/native/schema_handle.dart +++ b/packages/realm_dart/lib/src/native/schema_handle.dart @@ -5,12 +5,13 @@ import 'dart:ffi'; import 'package:ffi/ffi.dart'; import 'package:realm_common/realm_common.dart'; -import 'package:realm_dart/src/native/realm_core.dart'; import '../configuration.dart'; import 'handle_base.dart'; import 'realm_bindings.dart'; import 'realm_library.dart'; +import 'to_native.dart'; + class SchemaHandle extends HandleBase { SchemaHandle(Pointer pointer) : super(pointer, 24); diff --git a/packages/realm_dart/lib/src/native/session_handle.dart b/packages/realm_dart/lib/src/native/session_handle.dart index cda7a2676..0ebd78ee3 100644 --- a/packages/realm_dart/lib/src/native/session_handle.dart +++ b/packages/realm_dart/lib/src/native/session_handle.dart @@ -9,14 +9,15 @@ import 'package:ffi/ffi.dart'; import '../realm_dart.dart'; import '../scheduler.dart'; import '../session.dart'; // TODO: Remove this import +import 'convert_native.dart'; import 'handle_base.dart'; import 'realm_bindings.dart'; -import 'realm_core.dart'; // TODO: Remove this import import 'realm_handle.dart'; import 'realm_library.dart'; import 'rooted_handle.dart'; import 'user_handle.dart'; + class SessionHandle extends RootedHandleBase { @override bool get shouldRoot => true; diff --git a/packages/realm_dart/lib/src/native/set_handle.dart b/packages/realm_dart/lib/src/native/set_handle.dart index 406f16fad..35e8f778a 100644 --- a/packages/realm_dart/lib/src/native/set_handle.dart +++ b/packages/realm_dart/lib/src/native/set_handle.dart @@ -6,6 +6,7 @@ import 'dart:ffi'; import 'package:ffi/ffi.dart'; import '../realm_dart.dart'; // TODO: remove this import +import 'convert_native.dart'; import 'error_handling.dart'; import 'notification_token_handle.dart'; import 'query_handle.dart'; diff --git a/packages/realm_dart/lib/src/native/subscription_handle.dart b/packages/realm_dart/lib/src/native/subscription_handle.dart index 4c2c67a2a..9dfdca3ba 100644 --- a/packages/realm_dart/lib/src/native/subscription_handle.dart +++ b/packages/realm_dart/lib/src/native/subscription_handle.dart @@ -4,9 +4,9 @@ import 'dart:ffi'; import '../realm_class.dart'; // TODO: Remove this import +import 'from_native.dart'; import 'handle_base.dart'; import 'realm_bindings.dart'; -import 'realm_core.dart'; // TODO: Remove this import import 'realm_library.dart'; class SubscriptionHandle extends HandleBase { diff --git a/packages/realm_dart/lib/src/native/subscription_set_handle.dart b/packages/realm_dart/lib/src/native/subscription_set_handle.dart index a96cff307..9d55af468 100644 --- a/packages/realm_dart/lib/src/native/subscription_set_handle.dart +++ b/packages/realm_dart/lib/src/native/subscription_set_handle.dart @@ -5,14 +5,14 @@ import 'dart:ffi'; import 'package:cancellation_token/cancellation_token.dart'; import 'package:ffi/ffi.dart'; -import 'package:realm_dart/src/native/convert.dart'; import '../realm_dart.dart'; import '../scheduler.dart'; +import 'convert.dart'; +import 'convert_native.dart'; import 'error_handling.dart'; import 'mutable_subscription_set_handle.dart'; import 'realm_bindings.dart'; -import 'realm_core.dart'; // TODO: Remove this import import 'realm_handle.dart'; import 'realm_library.dart'; import 'results_handle.dart'; diff --git a/packages/realm_dart/lib/src/native/to_native.dart b/packages/realm_dart/lib/src/native/to_native.dart new file mode 100644 index 000000000..5a6fd7ec0 --- /dev/null +++ b/packages/realm_dart/lib/src/native/to_native.dart @@ -0,0 +1,172 @@ +import 'dart:convert'; +import 'dart:ffi'; +import 'dart:typed_data'; + +import '../realm_dart.dart'; +import '../realm_object.dart'; +import 'decimal128.dart'; +import 'realm_bindings.dart'; + +extension ListEx on List { + Pointer toCharPtr(Allocator allocator) { + return toUint8Ptr(allocator).cast(); + } + + Pointer toUint8Ptr(Allocator allocator) { + final nativeSize = length + 1; + final result = allocator(nativeSize); + final Uint8List native = result.asTypedList(nativeSize); + native.setAll(0, this); // copy + native.last = 0; // zero terminate + return result.cast(); + } +} + +extension StringEx on String { + Pointer toCharPtr(Allocator allocator) { + final units = utf8.encode(this); + return units.toCharPtr(allocator).cast(); + } + + Pointer toRealmString(Allocator allocator) { + final realmString = allocator(); + final units = utf8.encode(this); + realmString.ref.data = units.toCharPtr(allocator).cast(); + realmString.ref.size = units.length; + return realmString; + } +} + +extension NullableObjectEx on Object? { + Pointer toNative(Allocator allocator) { + final self = this; + final realmValue = allocator(); + if (self is RealmValue && self.type.isCollection) { + throw RealmError( + "Don't use _toPrimitiveValue if the value may contain collections. Use storeValue instead. This is a bug in the Realm Flutter SDK and should be reported to https://github.com/realm/realm-dart/issues/new"); + } + _intoRealmValue(self, realmValue.ref, allocator); + return realmValue; + } +} + +extension RealmValueTypeEx on RealmValueType { + String toQueryArgString() { + return switch (this) { + RealmValueType.nullValue => 'null', + RealmValueType.boolean => 'bool', + RealmValueType.string => 'string', + RealmValueType.int => 'int', + RealmValueType.double => 'double', + RealmValueType.object => 'link', + RealmValueType.objectId => 'objectid', + RealmValueType.dateTime => 'date', + RealmValueType.decimal => 'decimal', + RealmValueType.uuid => 'uuid', + RealmValueType.binary => 'binary', + RealmValueType.list => 'array', + RealmValueType.map => 'object', + }; + } +} + +const int _microsecondsPerSecond = 1000 * 1000; +const int _nanosecondsPerMicrosecond = 1000; + +void intoRealmQueryArg(Object? value, Pointer realmQueryArg, Allocator allocator) { + if (value is Iterable) { + realmQueryArg.ref.nb_args = value.length; + realmQueryArg.ref.is_list = true; + realmQueryArg.ref.arg = allocator(value.length); + int i = 0; + for (var item in value) { + _intoRealmValue(item, realmQueryArg.ref.arg[i], allocator); + i++; + } + } else { + realmQueryArg.ref.arg = allocator(); + realmQueryArg.ref.nb_args = 1; + realmQueryArg.ref.is_list = false; + _intoRealmValueHack(value, realmQueryArg.ref.arg.ref, allocator); + } +} + +void _intoRealmValueHack(Object? value, realm_value realmValue, Allocator allocator) { + if (value is GeoShape) { + _intoRealmValue(value.toString(), realmValue, allocator); + } else if (value is RealmValueType) { + _intoRealmValue(value.toQueryArgString(), realmValue, allocator); + } else { + _intoRealmValue(value, realmValue, allocator); + } +} + +void _intoRealmValue(Object? value, realm_value realmValue, Allocator allocator) { + if (value == null) { + realmValue.type = realm_value_type.RLM_TYPE_NULL; + } else if (value is RealmObjectBase) { + // when converting a RealmObjectBase to realm_value.link we assume the object is managed + final link = value.handle.asLink; + realmValue.values.link.target = link.targetKey; + realmValue.values.link.target_table = link.classKey; + realmValue.type = realm_value_type.RLM_TYPE_LINK; + } else if (value is int) { + realmValue.values.integer = value; + realmValue.type = realm_value_type.RLM_TYPE_INT; + } else if (value is bool) { + realmValue.values.boolean = value; + realmValue.type = realm_value_type.RLM_TYPE_BOOL; + } else if (value is String) { + String string = value; + final units = utf8.encode(string); + final result = allocator(units.length); + final Uint8List nativeString = result.asTypedList(units.length); + nativeString.setAll(0, units); + realmValue.values.string.data = result.cast(); + realmValue.values.string.size = units.length; + realmValue.type = realm_value_type.RLM_TYPE_STRING; + } else if (value is double) { + realmValue.values.dnum = value; + realmValue.type = realm_value_type.RLM_TYPE_DOUBLE; + } else if (value is ObjectId) { + final bytes = value.bytes; + for (var i = 0; i < 12; i++) { + realmValue.values.object_id.bytes[i] = bytes[i]; + } + realmValue.type = realm_value_type.RLM_TYPE_OBJECT_ID; + } else if (value is Uuid) { + final bytes = value.bytes.asUint8List(); + for (var i = 0; i < 16; i++) { + realmValue.values.uuid.bytes[i] = bytes[i]; + } + realmValue.type = realm_value_type.RLM_TYPE_UUID; + } else if (value is DateTime) { + final microseconds = value.toUtc().microsecondsSinceEpoch; + final seconds = microseconds ~/ _microsecondsPerSecond; + int nanoseconds = _nanosecondsPerMicrosecond * (microseconds % _microsecondsPerSecond); + if (microseconds < 0 && nanoseconds != 0) { + nanoseconds = nanoseconds - _nanosecondsPerMicrosecond * _microsecondsPerSecond; + } + realmValue.values.timestamp.seconds = seconds; + realmValue.values.timestamp.nanoseconds = nanoseconds; + realmValue.type = realm_value_type.RLM_TYPE_TIMESTAMP; + } else if (value is Decimal128) { + realmValue.values.decimal128 = value.value; + realmValue.type = realm_value_type.RLM_TYPE_DECIMAL128; + } else if (value is Uint8List) { + realmValue.type = realm_value_type.RLM_TYPE_BINARY; + realmValue.values.binary.size = value.length; + realmValue.values.binary.data = allocator(value.length); + realmValue.values.binary.data.asTypedList(value.length).setAll(0, value); + } else if (value is RealmValue) { + if (value is List) { + realmValue.type = realm_value_type.RLM_TYPE_LIST; + } else if (value is Map) { + realmValue.type = realm_value_type.RLM_TYPE_DICTIONARY; + } else { + return _intoRealmValue(value.value, realmValue, allocator); + } + } else { + throw RealmException("Property type ${value.runtimeType} not supported"); + } +} diff --git a/packages/realm_dart/lib/src/native/user_handle.dart b/packages/realm_dart/lib/src/native/user_handle.dart index d2b6c0193..8bddfc4fc 100644 --- a/packages/realm_dart/lib/src/native/user_handle.dart +++ b/packages/realm_dart/lib/src/native/user_handle.dart @@ -13,11 +13,11 @@ import '../scheduler.dart'; import '../user.dart'; // TODO: Remove this import import 'app_handle.dart'; import 'convert.dart'; +import 'convert_native.dart'; import 'credentials_handle.dart'; import 'error_handling.dart'; import 'handle_base.dart'; import 'realm_bindings.dart'; -import 'realm_core.dart'; import 'realm_library.dart'; // TODO: Remove this import class UserHandle extends HandleBase { From 90f2e9293d5ffb9c51da2e1aea7fdfef2682919d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Tue, 7 May 2024 10:54:11 +0200 Subject: [PATCH 62/68] Last leg.. for now --- .vscode/settings.json | 2 - .../lib/src/cli/common/archive.dart | 3 - .../realm_dart/lib/src/configuration.dart | 2 + .../realm_dart/lib/src/native/app_handle.dart | 12 +- .../src/native/async_open_task_handle.dart | 2 +- .../src/native/collection_changes_handle.dart | 4 +- .../lib/src/native/config_handle.dart | 19 +- .../lib/src/native/credentials_handle.dart | 4 +- .../realm_dart/lib/src/native/decimal128.dart | 2 +- .../lib/src/native/error_handling.dart | 4 +- packages/realm_dart/lib/src/native/ffi.dart | 4 + .../lib/src/native/from_native.dart | 21 +- .../lib/src/native/list_handle.dart | 4 +- .../lib/src/native/map_changes_handle.dart | 4 +- .../realm_dart/lib/src/native/map_handle.dart | 6 +- .../mutable_subscription_set_handle.dart | 4 +- .../src/native/notification_token_handle.dart | 25 ++ .../lib/src/native/object_handle.dart | 5 +- .../realm_dart/lib/src/native/realm_core.dart | 289 ++++++------------ .../lib/src/native/realm_handle.dart | 2 +- .../lib/src/native/realm_library.dart | 2 +- .../lib/src/native/results_handle.dart | 3 +- .../lib/src/native/rooted_handle.dart | 40 +++ .../lib/src/native/scheduler_handle.dart | 5 + .../lib/src/native/schema_handle.dart | 3 +- .../lib/src/native/session_handle.dart | 5 +- .../realm_dart/lib/src/native/set_handle.dart | 5 +- .../lib/src/native/subscription_handle.dart | 2 +- .../src/native/subscription_set_handle.dart | 2 +- .../lib/src/native/user_handle.dart | 10 +- packages/realm_dart/lib/src/realm_class.dart | 2 +- packages/realm_dart/lib/src/scheduler.dart | 4 +- packages/realm_dart/test/app_test.dart | 2 +- packages/realm_dart/test/realm_test.dart | 4 +- 34 files changed, 242 insertions(+), 265 deletions(-) create mode 100644 packages/realm_dart/lib/src/native/ffi.dart diff --git a/.vscode/settings.json b/.vscode/settings.json index 85ee6879d..8562c1d55 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -169,6 +169,4 @@ "__verbose_abort": "cpp" }, "cmake.sourceDirectory": "${workspaceFolder}/packages/realm_dart", - "dart.flutterSdkPath": "/Users/kasper/.puro/envs/stable/flutter", - "dart.sdkPath": "/Users/kasper/.puro/envs/stable/flutter/bin/cache/dart-sdk" } \ No newline at end of file diff --git a/packages/realm_dart/lib/src/cli/common/archive.dart b/packages/realm_dart/lib/src/cli/common/archive.dart index cb0c34061..eabca8f4a 100644 --- a/packages/realm_dart/lib/src/cli/common/archive.dart +++ b/packages/realm_dart/lib/src/cli/common/archive.dart @@ -1,9 +1,6 @@ // Copyright 2021 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -/// -library; - import 'dart:io'; import 'package:tar/tar.dart'; import 'package:path/path.dart' as path; diff --git a/packages/realm_dart/lib/src/configuration.dart b/packages/realm_dart/lib/src/configuration.dart index 4d02b5adc..2198e9cde 100644 --- a/packages/realm_dart/lib/src/configuration.dart +++ b/packages/realm_dart/lib/src/configuration.dart @@ -16,6 +16,8 @@ import 'native/realm_core.dart'; import 'realm_class.dart'; import 'user.dart'; +const encryptionKeySize = 64; + /// The signature of a callback used to determine if compaction /// should be attempted. /// diff --git a/packages/realm_dart/lib/src/native/app_handle.dart b/packages/realm_dart/lib/src/native/app_handle.dart index 6417ede86..9940d1fae 100644 --- a/packages/realm_dart/lib/src/native/app_handle.dart +++ b/packages/realm_dart/lib/src/native/app_handle.dart @@ -7,11 +7,11 @@ import 'dart:ffi'; import 'dart:io'; import 'dart:isolate'; -import 'package:ffi/ffi.dart'; +import 'ffi.dart'; import '../init.dart'; import '../logging.dart'; -import '../realm_class.dart'; // TODO: Remove this import +import '../realm_class.dart'; import '../scheduler.dart'; import 'convert.dart'; import 'convert_native.dart'; @@ -19,7 +19,7 @@ import 'credentials_handle.dart'; import 'error_handling.dart'; import 'handle_base.dart'; import 'realm_bindings.dart'; -import 'realm_core.dart'; // TODO: Remove this import +import 'realm_core.dart'; import 'realm_library.dart'; import 'user_handle.dart'; @@ -565,10 +565,10 @@ _AppConfigHandle _createAppConfig(AppConfiguration configuration, _HttpTransport realmLib.realm_app_config_set_sdk(handle.pointer, 'Dart'.toCharPtr(arena)); realmLib.realm_app_config_set_sdk_version(handle.pointer, libraryVersion.toCharPtr(arena)); - final deviceName = getDeviceName(); + final deviceName = realmCore.getDeviceName(); realmLib.realm_app_config_set_device_name(handle.pointer, deviceName.toCharPtr(arena)); - final deviceVersion = getDeviceVersion(); + final deviceVersion = realmCore.getDeviceVersion(); realmLib.realm_app_config_set_device_version(handle.pointer, deviceVersion.toCharPtr(arena)); realmLib.realm_app_config_set_framework_name(handle.pointer, (isFlutterPlatform ? 'Flutter' : 'Dart VM').toCharPtr(arena)); @@ -578,7 +578,7 @@ _AppConfigHandle _createAppConfig(AppConfiguration configuration, _HttpTransport realmLib.realm_app_config_set_default_request_timeout(handle.pointer, configuration.defaultRequestTimeout.inMilliseconds); - realmLib.realm_app_config_set_bundle_id(handle.pointer, getBundleId().toCharPtr(arena)); + realmLib.realm_app_config_set_bundle_id(handle.pointer, realmCore.getBundleId().toCharPtr(arena)); realmLib.realm_app_config_set_base_file_path(handle.pointer, configuration.baseFilePath.path.toCharPtr(arena)); realmLib.realm_app_config_set_metadata_mode(handle.pointer, configuration.metadataPersistenceMode.index); diff --git a/packages/realm_dart/lib/src/native/async_open_task_handle.dart b/packages/realm_dart/lib/src/native/async_open_task_handle.dart index c3cd2b1dd..483461231 100644 --- a/packages/realm_dart/lib/src/native/async_open_task_handle.dart +++ b/packages/realm_dart/lib/src/native/async_open_task_handle.dart @@ -1,7 +1,7 @@ import 'dart:ffi'; import 'package:cancellation_token/cancellation_token.dart'; -import 'package:ffi/ffi.dart'; +import 'ffi.dart'; import 'package:realm_dart/src/native/error_handling.dart'; import 'package:realm_dart/src/native/realm_bindings.dart'; diff --git a/packages/realm_dart/lib/src/native/collection_changes_handle.dart b/packages/realm_dart/lib/src/native/collection_changes_handle.dart index 9d9f4d594..ba5a63e29 100644 --- a/packages/realm_dart/lib/src/native/collection_changes_handle.dart +++ b/packages/realm_dart/lib/src/native/collection_changes_handle.dart @@ -3,9 +3,9 @@ import 'dart:ffi'; -import 'package:ffi/ffi.dart'; +import 'ffi.dart'; -import '../collections.dart'; // TODO: Remove this import +import '../collections.dart'; import 'from_native.dart'; import 'handle_base.dart'; import 'realm_bindings.dart'; diff --git a/packages/realm_dart/lib/src/native/config_handle.dart b/packages/realm_dart/lib/src/native/config_handle.dart index d23c08727..efa62208a 100644 --- a/packages/realm_dart/lib/src/native/config_handle.dart +++ b/packages/realm_dart/lib/src/native/config_handle.dart @@ -4,20 +4,20 @@ import 'dart:async'; import 'dart:ffi'; -import 'package:ffi/ffi.dart'; +import 'ffi.dart'; import 'package:realm_dart/src/native/error_handling.dart'; -import '../configuration.dart'; // TODO: Remove this import -import '../migration.dart'; // TODO: Remove this import -import '../realm_class.dart'; // TODO: Remove this import -import '../scheduler.dart'; // TODO: Remove this import -import '../user.dart'; // TODO: Remove this import +import '../configuration.dart'; +import '../migration.dart'; +import '../realm_class.dart'; +import '../scheduler.dart'; +import '../user.dart'; import 'convert_native.dart'; import 'handle_base.dart'; import 'realm_bindings.dart'; import 'realm_handle.dart'; import 'realm_library.dart'; -import 'schema_handle.dart'; // TODO: Remove this import +import 'schema_handle.dart'; class ConfigHandle extends HandleBase { ConfigHandle(Pointer pointer) : super(pointer, 512); @@ -134,8 +134,9 @@ class ConfigHandle extends HandleBase { realmLib.realm_config_set_force_sync_history(configHandle.pointer, true); } - if (config.encryptionKey != null) { - realmLib.realm_config_set_encryption_key(configHandle.pointer, config.encryptionKey!.toUint8Ptr(arena), encryptionKeySize); + final key = config.encryptionKey; + if (key != null) { + realmLib.realm_config_set_encryption_key(configHandle.pointer, key.toUint8Ptr(arena), key.length); } // For sync and for dynamic Realms, we need to have a complete view of the schema in Core. diff --git a/packages/realm_dart/lib/src/native/credentials_handle.dart b/packages/realm_dart/lib/src/native/credentials_handle.dart index fe31acd39..d742d9ac9 100644 --- a/packages/realm_dart/lib/src/native/credentials_handle.dart +++ b/packages/realm_dart/lib/src/native/credentials_handle.dart @@ -3,9 +3,9 @@ import 'dart:ffi'; -import 'package:ffi/ffi.dart'; +import 'ffi.dart'; -import '../credentials.dart'; // TODO: Remove this import +import '../credentials.dart'; import 'handle_base.dart'; import 'realm_bindings.dart'; import 'realm_library.dart'; diff --git a/packages/realm_dart/lib/src/native/decimal128.dart b/packages/realm_dart/lib/src/native/decimal128.dart index 157c4780e..ad4df4acd 100644 --- a/packages/realm_dart/lib/src/native/decimal128.dart +++ b/packages/realm_dart/lib/src/native/decimal128.dart @@ -4,7 +4,7 @@ import 'dart:convert'; import 'dart:ffi'; -import 'package:ffi/ffi.dart'; +import 'ffi.dart'; import 'package:realm_common/realm_common.dart' as common; import 'realm_bindings.dart'; diff --git a/packages/realm_dart/lib/src/native/error_handling.dart b/packages/realm_dart/lib/src/native/error_handling.dart index 5aeae56ef..f6be123cb 100644 --- a/packages/realm_dart/lib/src/native/error_handling.dart +++ b/packages/realm_dart/lib/src/native/error_handling.dart @@ -3,9 +3,9 @@ import 'dart:ffi'; -import 'package:ffi/ffi.dart'; +import 'ffi.dart'; -import '../realm_object.dart'; // TODO: Remove this import +import '../realm_object.dart'; import 'from_native.dart'; import 'realm_bindings.dart'; import 'realm_library.dart'; diff --git a/packages/realm_dart/lib/src/native/ffi.dart b/packages/realm_dart/lib/src/native/ffi.dart new file mode 100644 index 000000000..7a1ae302c --- /dev/null +++ b/packages/realm_dart/lib/src/native/ffi.dart @@ -0,0 +1,4 @@ +// Import this file instead of package:ffi/ffi.dart +// Hides StringUtf8Pointer.toNativeUtf8 and StringUtf16Pointer since these allows +// silently allocating memory. Use toUtf8Ptr instead +export 'package:ffi/ffi.dart' hide StringUtf8Pointer, StringUtf16Pointer; diff --git a/packages/realm_dart/lib/src/native/from_native.dart b/packages/realm_dart/lib/src/native/from_native.dart index bd218a9b2..9e54d6a53 100644 --- a/packages/realm_dart/lib/src/native/from_native.dart +++ b/packages/realm_dart/lib/src/native/from_native.dart @@ -3,7 +3,7 @@ import 'dart:ffi'; import 'dart:io'; import 'dart:typed_data'; -import 'package:ffi/ffi.dart'; +import 'ffi.dart'; import '../app.dart'; import '../configuration.dart'; @@ -337,3 +337,22 @@ class SyncErrorDetails { this.compensatingWrites, }); } + +extension PointerRealmValueEx on Pointer { + Object? toDartValue(Realm realm, Pointer Function()? getList, Pointer Function()? getMap) { + if (this == nullptr) { + throw RealmException("Can not convert nullptr realm_value to Dart value"); + } + return ref.toDartValue(realm: realm, getList: getList, getMap: getMap); + } + + List toStringList(int count) { + final result = List.filled(count, ''); + for (var i = 0; i < count; i++) { + final strValue = (this + i).ref.values.string; + result[i] = strValue.data.cast().toRealmDartString(length: strValue.size)!; + } + + return result; + } +} diff --git a/packages/realm_dart/lib/src/native/list_handle.dart b/packages/realm_dart/lib/src/native/list_handle.dart index cf7640600..66f265ebd 100644 --- a/packages/realm_dart/lib/src/native/list_handle.dart +++ b/packages/realm_dart/lib/src/native/list_handle.dart @@ -3,16 +3,14 @@ import 'dart:ffi'; -import 'package:ffi/ffi.dart'; - import '../realm_dart.dart'; import 'convert_native.dart'; import 'error_handling.dart'; +import 'ffi.dart'; import 'notification_token_handle.dart'; import 'object_handle.dart'; import 'query_handle.dart'; import 'realm_bindings.dart'; -import 'realm_core.dart'; // TODO: Remove this import import 'realm_handle.dart'; import 'realm_library.dart'; import 'results_handle.dart'; diff --git a/packages/realm_dart/lib/src/native/map_changes_handle.dart b/packages/realm_dart/lib/src/native/map_changes_handle.dart index 4b6291397..bccfbb909 100644 --- a/packages/realm_dart/lib/src/native/map_changes_handle.dart +++ b/packages/realm_dart/lib/src/native/map_changes_handle.dart @@ -3,12 +3,12 @@ import 'dart:ffi'; -import 'package:ffi/ffi.dart'; +import 'package:realm_dart/src/native/from_native.dart'; import '../collections.dart'; +import 'ffi.dart'; import 'handle_base.dart'; import 'realm_bindings.dart'; -import 'realm_core.dart'; import 'realm_library.dart'; class MapChangesHandle extends HandleBase { diff --git a/packages/realm_dart/lib/src/native/map_handle.dart b/packages/realm_dart/lib/src/native/map_handle.dart index 6eb5883d2..66ca44cfb 100644 --- a/packages/realm_dart/lib/src/native/map_handle.dart +++ b/packages/realm_dart/lib/src/native/map_handle.dart @@ -3,9 +3,9 @@ import 'dart:ffi'; -import 'package:ffi/ffi.dart'; +import 'ffi.dart'; -import '../realm_dart.dart'; // TODO: remove this import +import '../realm_dart.dart'; import 'convert_native.dart'; import 'error_handling.dart'; import 'map_changes_handle.dart'; @@ -13,7 +13,7 @@ import 'notification_token_handle.dart'; import 'object_handle.dart'; import 'query_handle.dart'; import 'realm_bindings.dart'; -import 'realm_core.dart'; // TODO: remove this import +// TODO: remove this import import 'realm_handle.dart'; import 'realm_library.dart'; import 'results_handle.dart'; diff --git a/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart b/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart index 1f33e28cd..8e6a4aeab 100644 --- a/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart +++ b/packages/realm_dart/lib/src/native/mutable_subscription_set_handle.dart @@ -3,9 +3,9 @@ import 'dart:ffi'; -import 'package:ffi/ffi.dart'; +import 'ffi.dart'; -import '../realm_dart.dart'; // TODO: Remove this import +import '../realm_dart.dart'; import 'convert_native.dart'; import 'error_handling.dart'; import 'realm_bindings.dart'; diff --git a/packages/realm_dart/lib/src/native/notification_token_handle.dart b/packages/realm_dart/lib/src/native/notification_token_handle.dart index 9d02ac649..eebee574e 100644 --- a/packages/realm_dart/lib/src/native/notification_token_handle.dart +++ b/packages/realm_dart/lib/src/native/notification_token_handle.dart @@ -1,10 +1,35 @@ import 'dart:ffi'; +import '../realm_dart.dart'; +import 'collection_changes_handle.dart'; +import 'from_native.dart'; import 'realm_bindings.dart'; import 'realm_handle.dart'; +import 'realm_library.dart'; import 'rooted_handle.dart'; class NotificationTokenHandle extends RootedHandleBase { NotificationTokenHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 32); } +void collectionChangeCallback(Pointer userdata, Pointer data) { + final NotificationsController controller = userdata.toObject(); + + if (data == nullptr) { + controller.onError(RealmError("Invalid notifications data received")); + return; + } + + try { + final clonedData = realmLib.realm_clone(data.cast()); + if (clonedData == nullptr) { + controller.onError(RealmError("Error while cloning notifications data")); + return; + } + + final changesHandle = CollectionChangesHandle(clonedData.cast()); + controller.onChanges(changesHandle); + } catch (e) { + controller.onError(RealmError("Error handling change notifications. Error: $e")); + } +} diff --git a/packages/realm_dart/lib/src/native/object_handle.dart b/packages/realm_dart/lib/src/native/object_handle.dart index 741f5421e..9e1277a56 100644 --- a/packages/realm_dart/lib/src/native/object_handle.dart +++ b/packages/realm_dart/lib/src/native/object_handle.dart @@ -3,9 +3,9 @@ import 'dart:ffi'; -import 'package:ffi/ffi.dart'; +import 'ffi.dart'; -import '../realm_dart.dart'; // TODO: Remove this import +import '../realm_dart.dart'; import 'convert_native.dart'; import 'error_handling.dart'; import 'handle_base.dart'; @@ -13,7 +13,6 @@ import 'list_handle.dart'; import 'map_handle.dart'; import 'notification_token_handle.dart'; import 'realm_bindings.dart'; -import 'realm_core.dart'; // TODO: Remove this import import 'realm_handle.dart'; import 'realm_library.dart'; import 'results_handle.dart'; diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index ba644848c..7c095fec4 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -6,22 +6,18 @@ import 'dart:ffi'; import 'dart:io'; import 'package:crypto/crypto.dart'; -// Hide StringUtf8Pointer.toNativeUtf8 and StringUtf16Pointer since these allows silently allocating memory. Use toUtf8Ptr instead -import 'package:ffi/ffi.dart' hide StringUtf8Pointer, StringUtf16Pointer; import 'package:path/path.dart' as path; import 'package:pubspec_parse/pubspec_parse.dart'; import '../init.dart'; import '../realm_class.dart'; import '../scheduler.dart'; -import 'collection_changes_handle.dart'; import 'convert_native.dart'; import 'error_handling.dart'; -import 'list_handle.dart'; -import 'map_handle.dart'; -import 'realm_bindings.dart'; +import 'ffi.dart'; import 'realm_library.dart'; -import 'rooted_handle.dart'; + +final realmCore = RealmCore._(); final _pluginLib = () { if (!isFlutterPlatform) { @@ -44,143 +40,14 @@ final _pluginLib = () { return pluginLib; }(); -var realmCore = _RealmCore(); - -const encryptionKeySize = 64; -String getFilesPath() { - return realmLib.realm_dart_get_files_path().cast().toRealmDartString()!; -} - -String getDeviceName() { - if (Platform.isAndroid || Platform.isIOS) { - return realmLib.realm_dart_get_device_name().cast().toRealmDartString()!; - } - - return ""; -} - -String getDeviceVersion() { - if (Platform.isAndroid || Platform.isIOS) { - return realmLib.realm_dart_get_device_version().cast().toRealmDartString()!; - } - - return ""; -} - -String getRealmLibraryCpuArchitecture() { - return realmLib.realm_get_library_cpu_arch().cast().toDartString(); -} - -String getBundleId() { - readBundleId() { - try { - if (!isFlutterPlatform || Platform.environment.containsKey('FLUTTER_TEST')) { - var pubspecPath = path.join(path.current, 'pubspec.yaml'); - var pubspecFile = File(pubspecPath); - - if (pubspecFile.existsSync()) { - final pubspec = Pubspec.parse(pubspecFile.readAsStringSync()); - return pubspec.name; - } - } - - if (Platform.isAndroid) { - return realmLib.realm_dart_get_bundle_id().cast().toDartString(); - } - - final getBundleIdFunc = _pluginLib.lookupFunction Function(), Pointer Function()>("realm_dart_get_bundle_id"); - final bundleIdPtr = getBundleIdFunc(); - return bundleIdPtr.cast().toDartString(); - } on Exception catch (_) { - //Never fail on bundleId. Use fallback value. - } - - //Fallback value - return "realm_bundle_id"; - } - - String bundleId = readBundleId(); - const salt = [82, 101, 97, 108, 109, 32, 105, 115, 32, 103, 114, 101, 97, 116]; - return base64Encode(sha256.convert([...salt, ...utf8.encode(bundleId)]).bytes); -} - -void createCollection(Realm realm, RealmValue value, Pointer Function() createList, Pointer Function() createMap) { - CollectionHandleBase? collectionHandle; - try { - switch (value.collectionType) { - case RealmCollectionType.list: - final listHandle = ListHandle(createList(), realm.handle); - collectionHandle = listHandle; - - final list = realm.createList(listHandle, null); - - // Necessary since Core will not clear the collection if the value was already a collection - list.clear(); - - for (final item in value.value as List) { - list.add(item); - } - case RealmCollectionType.map: - final mapHandle = MapHandle(createMap(), realm.handle); - collectionHandle = mapHandle; - - final map = realm.createMap(mapHandle, null); - - // Necessary since Core will not clear the collection if the value was already a collection - map.clear(); - - for (final kvp in (value.value as Map).entries) { - map[kvp.key] = kvp.value; - } - default: - throw RealmStateError('_createCollection invoked with type that is not list or map.'); - } - } finally { - collectionHandle?.release(); - } -} - -void collectionChangeCallback(Pointer userdata, Pointer data) { - final NotificationsController controller = userdata.toObject(); - - if (data == nullptr) { - controller.onError(RealmError("Invalid notifications data received")); - return; - } - - try { - final clonedData = realmLib.realm_clone(data.cast()); - if (clonedData == nullptr) { - controller.onError(RealmError("Error while cloning notifications data")); - return; - } - - final changesHandle = CollectionChangesHandle(clonedData.cast()); - controller.onChanges(changesHandle); - } catch (e) { - controller.onError(RealmError("Error handling change notifications. Error: $e")); - } -} - -// All access to Realm Core functionality goes through this class -class _RealmCore { - // ignore: unused_field - static late final _RealmCore _instance; - - _RealmCore() { - // This disables creation of a second _RealmCore instance effectively making `realmCore` global variable readonly - _instance = this; - - // This prevents reentrance if `realmCore` global variable is accessed during _RealmCore construction - realmCore = this; - } - - void loggerAttach() { - realmLib.realm_dart_attach_logger(scheduler.nativePort); - } +class RealmCore { + RealmCore._(); + + // For debugging + int get threadId => realmLib.realm_dart_get_thread_id(); - void loggerDetach() { - realmLib.realm_dart_detach_logger(scheduler.nativePort); + void clearCachedApps() { + realmLib.realm_clear_cached_apps(); } // for debugging only. Enable in realm_dart.cpp @@ -188,11 +55,6 @@ class _RealmCore { // realmLib.realm_dart_gc(); // } - void invokeScheduler(int workQueue) { - final queuePointer = Pointer.fromAddress(workQueue); - realmLib.realm_scheduler_perform_work(queuePointer); - } - void deleteRealmFiles(String path) { using((arena) { final realmDeleted = arena(); @@ -200,34 +62,15 @@ class _RealmCore { }); } - // For debugging - // ignore: unused_element - int get _threadId => realmLib.realm_dart_get_thread_id(); - - void logMessage(LogCategory category, LogLevel logLevel, String message) { + List getAllCategoryNames() { return using((arena) { - realmLib.realm_dart_log(logLevel.index, category.toString().toCharPtr(arena), message.toCharPtr(arena)); + final count = realmLib.realm_get_category_names(0, nullptr); + final outValues = arena>(count); + realmLib.realm_get_category_names(count, outValues); + return [for (int i = 0; i < count; i++) outValues[i].cast().toDartString()]; }); } - String getDefaultBaseUrl() { - return realmLib.realm_app_get_default_base_url().cast().toRealmDartString()!; - } - - void clearCachedApps() { - realmLib.realm_clear_cached_apps(); - } - - String _getAppDirectoryFromPlugin() { - assert(isFlutterPlatform); - - final getAppDirFunc = _pluginLib.lookupFunction Function(), Pointer Function()>("realm_dart_get_app_directory"); - final dirNamePtr = getAppDirFunc(); - final dirName = Platform.isWindows ? dirNamePtr.cast().toDartString() : dirNamePtr.cast().toDartString(); - - return dirName; - } - String getAppDirectory() { try { if (!isFlutterPlatform || Platform.environment.containsKey('FLUTTER_TEST')) { @@ -237,7 +80,7 @@ class _RealmCore { // Flutter from here on.. if (Platform.isAndroid || Platform.isIOS) { - return getFilesPath(); + return _getFilesPath(); } if (Platform.isLinux) { @@ -259,38 +102,90 @@ class _RealmCore { } } - void setLogLevel(LogLevel level, {required LogCategory category}) { - using((arena) { - realmLib.realm_set_log_level_category(category.toString().toCharPtr(arena), level.index); - }); + String getBundleId() { + readBundleId() { + try { + if (!isFlutterPlatform || Platform.environment.containsKey('FLUTTER_TEST')) { + var pubspecPath = path.join(path.current, 'pubspec.yaml'); + var pubspecFile = File(pubspecPath); + + if (pubspecFile.existsSync()) { + final pubspec = Pubspec.parse(pubspecFile.readAsStringSync()); + return pubspec.name; + } + } + + if (Platform.isAndroid) { + return realmLib.realm_dart_get_bundle_id().cast().toDartString(); + } + + final getBundleIdFunc = _pluginLib.lookupFunction Function(), Pointer Function()>("realm_dart_get_bundle_id"); + final bundleIdPtr = getBundleIdFunc(); + return bundleIdPtr.cast().toDartString(); + } on Exception catch (_) { + //Never fail on bundleId. Use fallback value. + } + + //Fallback value + return "realm_bundle_id"; + } + + String bundleId = readBundleId(); + const salt = [82, 101, 97, 108, 109, 32, 105, 115, 32, 103, 114, 101, 97, 116]; + return base64Encode(sha256.convert([...salt, ...utf8.encode(bundleId)]).bytes); + } + + String getDefaultBaseUrl() { + return realmLib.realm_app_get_default_base_url().cast().toRealmDartString()!; } - List getAllCategoryNames() { + String getDeviceName() { + if (Platform.isAndroid || Platform.isIOS) { + return realmLib.realm_dart_get_device_name().cast().toRealmDartString()!; + } + + return ""; + } + + String getDeviceVersion() { + if (Platform.isAndroid || Platform.isIOS) { + return realmLib.realm_dart_get_device_version().cast().toRealmDartString()!; + } + + return ""; + } + + String getRealmLibraryCpuArchitecture() { + return realmLib.realm_get_library_cpu_arch().cast().toDartString(); + } + + void loggerAttach() => realmLib.realm_dart_attach_logger(scheduler.nativePort); + + void loggerDetach() => realmLib.realm_dart_detach_logger(scheduler.nativePort); + + void logMessage(LogCategory category, LogLevel logLevel, String message) { return using((arena) { - final count = realmLib.realm_get_category_names(0, nullptr); - final outValues = arena>(count); - realmLib.realm_get_category_names(count, outValues); - return [for (int i = 0; i < count; i++) outValues[i].cast().toDartString()]; + realmLib.realm_dart_log(logLevel.index, category.toString().toCharPtr(arena), message.toCharPtr(arena)); }); } -} -extension PointerRealmValueEx on Pointer { - Object? toDartValue(Realm realm, Pointer Function()? getList, Pointer Function()? getMap) { - if (this == nullptr) { - throw RealmException("Can not convert nullptr realm_value to Dart value"); - } - return ref.toDartValue(realm: realm, getList: getList, getMap: getMap); + void setLogLevel(LogLevel level, {required LogCategory category}) { + using((arena) { + realmLib.realm_set_log_level_category(category.toString().toCharPtr(arena), level.index); + }); } - List toStringList(int count) { - final result = List.filled(count, ''); - for (var i = 0; i < count; i++) { - final strValue = (this + i).ref.values.string; - result[i] = strValue.data.cast().toRealmDartString(length: strValue.size)!; - } + String _getAppDirectoryFromPlugin() { + assert(isFlutterPlatform); - return result; + final getAppDirFunc = _pluginLib.lookupFunction Function(), Pointer Function()>("realm_dart_get_app_directory"); + final dirNamePtr = getAppDirFunc(); + final dirName = Platform.isWindows ? dirNamePtr.cast().toDartString() : dirNamePtr.cast().toDartString(); + + return dirName; } -} + String _getFilesPath() { + return realmLib.realm_dart_get_files_path().cast().toRealmDartString()!; + } +} diff --git a/packages/realm_dart/lib/src/native/realm_handle.dart b/packages/realm_dart/lib/src/native/realm_handle.dart index 9e6931325..fe5a94001 100644 --- a/packages/realm_dart/lib/src/native/realm_handle.dart +++ b/packages/realm_dart/lib/src/native/realm_handle.dart @@ -5,7 +5,7 @@ import 'dart:async'; import 'dart:ffi'; import 'package:cancellation_token/cancellation_token.dart'; -import 'package:ffi/ffi.dart'; +import 'ffi.dart'; import 'package:realm_common/realm_common.dart'; import '../logging.dart'; diff --git a/packages/realm_dart/lib/src/native/realm_library.dart b/packages/realm_dart/lib/src/native/realm_library.dart index f747932df..678c395b1 100644 --- a/packages/realm_dart/lib/src/native/realm_library.dart +++ b/packages/realm_dart/lib/src/native/realm_library.dart @@ -1,7 +1,7 @@ // Copyright 2024 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -import 'package:ffi/ffi.dart'; +import 'ffi.dart'; import 'package:realm_common/realm_common.dart'; import 'package:realm_dart/src/init.dart'; import 'package:realm_dart/src/native/realm_bindings.dart'; diff --git a/packages/realm_dart/lib/src/native/results_handle.dart b/packages/realm_dart/lib/src/native/results_handle.dart index 9d85ed071..0f4277776 100644 --- a/packages/realm_dart/lib/src/native/results_handle.dart +++ b/packages/realm_dart/lib/src/native/results_handle.dart @@ -3,7 +3,7 @@ import 'dart:ffi'; -import 'package:ffi/ffi.dart'; +import 'ffi.dart'; import '../realm_dart.dart'; import 'convert_native.dart'; @@ -12,7 +12,6 @@ import 'notification_token_handle.dart'; import 'object_handle.dart'; import 'query_handle.dart'; import 'realm_bindings.dart'; -import 'realm_core.dart'; import 'realm_handle.dart'; import 'realm_library.dart'; import 'rooted_handle.dart'; diff --git a/packages/realm_dart/lib/src/native/rooted_handle.dart b/packages/realm_dart/lib/src/native/rooted_handle.dart index f1301dd42..85ba4efaf 100644 --- a/packages/realm_dart/lib/src/native/rooted_handle.dart +++ b/packages/realm_dart/lib/src/native/rooted_handle.dart @@ -3,7 +3,11 @@ import 'dart:ffi'; +import '../realm_class.dart'; import 'handle_base.dart'; +import 'list_handle.dart'; +import 'map_handle.dart'; +import 'realm_bindings.dart'; import 'realm_handle.dart'; class FinalizationToken { @@ -43,3 +47,39 @@ abstract class RootedHandleBase extends HandleBase { abstract class CollectionHandleBase extends RootedHandleBase { CollectionHandleBase(super.root, super.pointer, super.size); } + +void createCollection(Realm realm, RealmValue value, Pointer Function() createList, Pointer Function() createMap) { + CollectionHandleBase? collectionHandle; + try { + switch (value.collectionType) { + case RealmCollectionType.list: + final listHandle = ListHandle(createList(), realm.handle); + collectionHandle = listHandle; + + final list = realm.createList(listHandle, null); + + // Necessary since Core will not clear the collection if the value was already a collection + list.clear(); + + for (final item in value.value as List) { + list.add(item); + } + case RealmCollectionType.map: + final mapHandle = MapHandle(createMap(), realm.handle); + collectionHandle = mapHandle; + + final map = realm.createMap(mapHandle, null); + + // Necessary since Core will not clear the collection if the value was already a collection + map.clear(); + + for (final kvp in (value.value as Map).entries) { + map[kvp.key] = kvp.value; + } + default: + throw RealmStateError('_createCollection invoked with type that is not list or map.'); + } + } finally { + collectionHandle?.release(); + } +} diff --git a/packages/realm_dart/lib/src/native/scheduler_handle.dart b/packages/realm_dart/lib/src/native/scheduler_handle.dart index 51d396788..4ad210542 100644 --- a/packages/realm_dart/lib/src/native/scheduler_handle.dart +++ b/packages/realm_dart/lib/src/native/scheduler_handle.dart @@ -14,4 +14,9 @@ class SchedulerHandle extends HandleBase { final schedulerPtr = realmLib.realm_dart_create_scheduler(isolateId, sendPort); return SchedulerHandle._(schedulerPtr); } + + void invoke(int workQueue) { + final queuePointer = Pointer.fromAddress(workQueue); + realmLib.realm_scheduler_perform_work(queuePointer); + } } diff --git a/packages/realm_dart/lib/src/native/schema_handle.dart b/packages/realm_dart/lib/src/native/schema_handle.dart index 4eb37873f..e11512d46 100644 --- a/packages/realm_dart/lib/src/native/schema_handle.dart +++ b/packages/realm_dart/lib/src/native/schema_handle.dart @@ -3,7 +3,7 @@ import 'dart:ffi'; -import 'package:ffi/ffi.dart'; +import 'ffi.dart'; import 'package:realm_common/realm_common.dart'; import '../configuration.dart'; @@ -12,7 +12,6 @@ import 'realm_bindings.dart'; import 'realm_library.dart'; import 'to_native.dart'; - class SchemaHandle extends HandleBase { SchemaHandle(Pointer pointer) : super(pointer, 24); diff --git a/packages/realm_dart/lib/src/native/session_handle.dart b/packages/realm_dart/lib/src/native/session_handle.dart index 0ebd78ee3..0d0119d22 100644 --- a/packages/realm_dart/lib/src/native/session_handle.dart +++ b/packages/realm_dart/lib/src/native/session_handle.dart @@ -4,11 +4,11 @@ import 'dart:ffi'; import 'package:cancellation_token/cancellation_token.dart'; -import 'package:ffi/ffi.dart'; +import 'ffi.dart'; import '../realm_dart.dart'; import '../scheduler.dart'; -import '../session.dart'; // TODO: Remove this import +import '../session.dart'; import 'convert_native.dart'; import 'handle_base.dart'; import 'realm_bindings.dart'; @@ -17,7 +17,6 @@ import 'realm_library.dart'; import 'rooted_handle.dart'; import 'user_handle.dart'; - class SessionHandle extends RootedHandleBase { @override bool get shouldRoot => true; diff --git a/packages/realm_dart/lib/src/native/set_handle.dart b/packages/realm_dart/lib/src/native/set_handle.dart index 35e8f778a..6135ae620 100644 --- a/packages/realm_dart/lib/src/native/set_handle.dart +++ b/packages/realm_dart/lib/src/native/set_handle.dart @@ -3,15 +3,14 @@ import 'dart:ffi'; -import 'package:ffi/ffi.dart'; +import 'ffi.dart'; -import '../realm_dart.dart'; // TODO: remove this import +import '../realm_dart.dart'; import 'convert_native.dart'; import 'error_handling.dart'; import 'notification_token_handle.dart'; import 'query_handle.dart'; import 'realm_bindings.dart'; -import 'realm_core.dart'; // TODO: Remove this import import 'realm_handle.dart'; import 'realm_library.dart'; import 'results_handle.dart'; diff --git a/packages/realm_dart/lib/src/native/subscription_handle.dart b/packages/realm_dart/lib/src/native/subscription_handle.dart index 9dfdca3ba..06eb4cf87 100644 --- a/packages/realm_dart/lib/src/native/subscription_handle.dart +++ b/packages/realm_dart/lib/src/native/subscription_handle.dart @@ -3,7 +3,7 @@ import 'dart:ffi'; -import '../realm_class.dart'; // TODO: Remove this import +import '../realm_class.dart'; import 'from_native.dart'; import 'handle_base.dart'; import 'realm_bindings.dart'; diff --git a/packages/realm_dart/lib/src/native/subscription_set_handle.dart b/packages/realm_dart/lib/src/native/subscription_set_handle.dart index 9d55af468..a4eadae0a 100644 --- a/packages/realm_dart/lib/src/native/subscription_set_handle.dart +++ b/packages/realm_dart/lib/src/native/subscription_set_handle.dart @@ -4,7 +4,7 @@ import 'dart:ffi'; import 'package:cancellation_token/cancellation_token.dart'; -import 'package:ffi/ffi.dart'; +import 'ffi.dart'; import '../realm_dart.dart'; import '../scheduler.dart'; diff --git a/packages/realm_dart/lib/src/native/user_handle.dart b/packages/realm_dart/lib/src/native/user_handle.dart index 8bddfc4fc..8b9806cbb 100644 --- a/packages/realm_dart/lib/src/native/user_handle.dart +++ b/packages/realm_dart/lib/src/native/user_handle.dart @@ -5,12 +5,12 @@ import 'dart:async'; import 'dart:convert'; import 'dart:ffi'; -import 'package:ffi/ffi.dart'; +import 'ffi.dart'; -import '../credentials.dart'; // TODO: Remove this import -import '../realm_dart.dart'; // TODO: Remove this import +import '../credentials.dart'; +import '../realm_dart.dart'; import '../scheduler.dart'; -import '../user.dart'; // TODO: Remove this import +import '../user.dart'; import 'app_handle.dart'; import 'convert.dart'; import 'convert_native.dart'; @@ -18,7 +18,7 @@ import 'credentials_handle.dart'; import 'error_handling.dart'; import 'handle_base.dart'; import 'realm_bindings.dart'; -import 'realm_library.dart'; // TODO: Remove this import +import 'realm_library.dart'; class UserHandle extends HandleBase { UserHandle(Pointer pointer) : super(pointer, 24); diff --git a/packages/realm_dart/lib/src/realm_class.dart b/packages/realm_dart/lib/src/realm_class.dart index 162fcf666..8c80c79df 100644 --- a/packages/realm_dart/lib/src/realm_class.dart +++ b/packages/realm_dart/lib/src/realm_class.dart @@ -63,6 +63,7 @@ export 'app.dart' show AppException, App, MetadataPersistenceMode, AppConfigurat export 'collections.dart' show Move; export "configuration.dart" show + encryptionKeySize, AfterResetCallback, BeforeResetCallback, ClientResetCallback, @@ -91,7 +92,6 @@ export 'list.dart' show RealmList, RealmListOfObject, RealmListChanges, ListExte export 'logging.dart' hide RealmLoggerInternal; export 'map.dart' show RealmMap, RealmMapChanges, RealmMapOfObject; export 'migration.dart' show Migration; -export 'native/realm_core.dart' show encryptionKeySize; export 'native/decimal128.dart' show Decimal128; export 'realm_object.dart' show diff --git a/packages/realm_dart/lib/src/scheduler.dart b/packages/realm_dart/lib/src/scheduler.dart index 5ee31931c..104cb1af1 100644 --- a/packages/realm_dart/lib/src/scheduler.dart +++ b/packages/realm_dart/lib/src/scheduler.dart @@ -1,12 +1,10 @@ // Copyright 2022 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 -import 'dart:async'; import 'dart:ffi'; import 'dart:isolate'; -import 'package:realm_dart/src/logging.dart'; -import 'native/realm_core.dart'; +import 'package:realm_dart/src/logging.dart'; import 'native/scheduler_handle.dart'; import 'realm_class.dart'; diff --git a/packages/realm_dart/test/app_test.dart b/packages/realm_dart/test/app_test.dart index 6ed88d120..b543c0946 100644 --- a/packages/realm_dart/test/app_test.dart +++ b/packages/realm_dart/test/app_test.dart @@ -322,7 +322,7 @@ void main() { final text = isFlutterPlatform ? "realm_tests" : "realm_dart"; const salt = [82, 101, 97, 108, 109, 32, 105, 115, 32, 103, 114, 101, 97, 116]; final expected = base64Encode(sha256.convert([...salt, ...utf8.encode(text)]).bytes); - expect(getBundleId(), expected); + expect(realmCore.getBundleId(), expected); }); test('app.getById without apps returns null', () { diff --git a/packages/realm_dart/test/realm_test.dart b/packages/realm_dart/test/realm_test.dart index 74529b469..d8c946499 100644 --- a/packages/realm_dart/test/realm_test.dart +++ b/packages/realm_dart/test/realm_test.dart @@ -1846,8 +1846,8 @@ void main() { matcher = isEmpty; } - expect(getDeviceName(), matcher); - expect(getDeviceVersion(), matcher); + expect(realmCore.getDeviceName(), matcher); + expect(realmCore.getDeviceVersion(), matcher); }); test('Realm path with unicode symbols', () { From 1922252f489a5a2e6928c94d7cad4325611bc754 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Wed, 8 May 2024 17:10:25 +0200 Subject: [PATCH 63/68] PR feedback --- .vscode/settings.json | 2 +- .../realm_dart/lib/src/cli/common/utils.dart | 2 +- .../realm_dart/lib/src/configuration.dart | 2 +- .../realm_dart/lib/src/native/app_handle.dart | 215 ++---------------- .../src/native/async_open_task_handle.dart | 2 +- .../src/native/collection_handle_base.dart | 51 +++++ .../lib/src/native/config_handle.dart | 5 +- .../lib/src/native/error_handling.dart | 17 +- .../lib/src/native/http_transport_handle.dart | 153 +++++++++++++ .../lib/src/native/list_handle.dart | 2 +- .../realm_dart/lib/src/native/map_handle.dart | 6 +- .../lib/src/native/object_handle.dart | 6 +- .../realm_dart/lib/src/native/realm_core.dart | 6 +- .../lib/src/native/realm_handle.dart | 37 ++- .../lib/src/native/rooted_handle.dart | 44 ---- .../realm_dart/lib/src/native/to_native.dart | 5 +- .../lib/src/native/user_handle.dart | 16 +- packages/realm_dart/test/app_test.dart | 2 +- packages/realm_dart/test/baas_helper.dart | 4 +- 19 files changed, 281 insertions(+), 296 deletions(-) create mode 100644 packages/realm_dart/lib/src/native/collection_handle_base.dart create mode 100644 packages/realm_dart/lib/src/native/http_transport_handle.dart diff --git a/.vscode/settings.json b/.vscode/settings.json index 8562c1d55..483d755b2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -168,5 +168,5 @@ "__tuple": "cpp", "__verbose_abort": "cpp" }, - "cmake.sourceDirectory": "${workspaceFolder}/packages/realm_dart", + "cmake.sourceDirectory": "${workspaceFolder}/packages/realm_dart" } \ No newline at end of file diff --git a/packages/realm_dart/lib/src/cli/common/utils.dart b/packages/realm_dart/lib/src/cli/common/utils.dart index c7d5c0851..78ac701f9 100644 --- a/packages/realm_dart/lib/src/cli/common/utils.dart +++ b/packages/realm_dart/lib/src/cli/common/utils.dart @@ -20,7 +20,7 @@ extension StringEx on String { bool isRealmCI = Platform.environment['REALM_CI'] != null; -FutureOr safe(FutureOr Function() f, {String message = 'Ignoring error', Function(Object e, StackTrace s)? onError}) async { +FutureOr safe(FutureOr Function() f, {String message = 'Ignoring error', void Function(Object e, StackTrace s)? onError}) async { try { return await f(); } catch (e, s) { diff --git a/packages/realm_dart/lib/src/configuration.dart b/packages/realm_dart/lib/src/configuration.dart index 2198e9cde..44c11ce92 100644 --- a/packages/realm_dart/lib/src/configuration.dart +++ b/packages/realm_dart/lib/src/configuration.dart @@ -658,7 +658,7 @@ class ClientResetError extends SyncError { throw RealmException("Missing `originalFilePath`"); } - return _app.handle.immediatelyRunFileActions(originalFilePath!); + return _app.handle.resetRealm(originalFilePath!); } } diff --git a/packages/realm_dart/lib/src/native/app_handle.dart b/packages/realm_dart/lib/src/native/app_handle.dart index 9940d1fae..c766c0453 100644 --- a/packages/realm_dart/lib/src/native/app_handle.dart +++ b/packages/realm_dart/lib/src/native/app_handle.dart @@ -2,22 +2,20 @@ // SPDX-License-Identifier: Apache-2.0 import 'dart:async'; -import 'dart:convert'; import 'dart:ffi'; import 'dart:io'; import 'dart:isolate'; -import 'ffi.dart'; - import '../init.dart'; -import '../logging.dart'; import '../realm_class.dart'; import '../scheduler.dart'; import 'convert.dart'; import 'convert_native.dart'; import 'credentials_handle.dart'; import 'error_handling.dart'; +import 'ffi.dart'; import 'handle_base.dart'; +import 'http_transport_handle.dart'; import 'realm_bindings.dart'; import 'realm_core.dart'; import 'realm_library.dart'; @@ -34,7 +32,7 @@ class AppHandle extends HandleBase { _firstTime = false; realmLib.realm_clear_cached_apps(); } - final httpTransportHandle = _createHttpTransport(configuration.httpClient); + final httpTransportHandle = HttpTransportHandle.from(configuration.httpClient); final appConfigHandle = _createAppConfig(configuration, httpTransportHandle); return AppHandle(realmLib.realm_app_create_cached(appConfigHandle.pointer)); } @@ -88,7 +86,7 @@ class AppHandle extends HandleBase { createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseLastErrorIfFalse("Remove user failed"); + .raiseLastErrorIfFalse(); return completer.future; } @@ -99,7 +97,7 @@ class AppHandle extends HandleBase { pointer, user.pointer, ) - .raiseLastErrorIfFalse("Switch user failed"); + .raiseLastErrorIfFalse(); }); } @@ -121,7 +119,7 @@ class AppHandle extends HandleBase { createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseLastErrorIfFalse("Update base URL failed"); + .raiseLastErrorIfFalse(); }); return completer.future; } @@ -136,7 +134,7 @@ class AppHandle extends HandleBase { createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseLastErrorIfFalse("Refresh custom data failed"); + .raiseLastErrorIfFalse(); return completer.future; } @@ -144,7 +142,7 @@ class AppHandle extends HandleBase { return realmLib.realm_app_get_app_id(pointer).cast().toRealmDartString()!; } - Future logIn(CredentialsHandle credentials) async { + Future logIn(CredentialsHandle credentials) { final completer = Completer(); realmLib .realm_app_log_in_with_credentials( @@ -154,8 +152,8 @@ class AppHandle extends HandleBase { createAsyncUserCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseLastErrorIfFalse("Login failed"); - return await completer.future; + .raiseLastErrorIfFalse(); + return completer.future; } Future registerUser(String email, String password) { @@ -175,7 +173,7 @@ class AppHandle extends HandleBase { return completer.future; } - Future confirmUser(String token, String tokenId) async { + Future confirmUser(String token, String tokenId) { final completer = Completer(); using((arena) { realmLib @@ -189,7 +187,7 @@ class AppHandle extends HandleBase { ) .raiseLastErrorIfFalse(); }); - return await completer.future; + return completer.future; } Future resendConfirmation(String email) { @@ -276,31 +274,6 @@ class AppHandle extends HandleBase { return completer.future; } - Future logOut(UserHandle? user) { - final completer = Completer(); - if (user == null) { - realmLib - .realm_app_log_out_current_user( - pointer, - realmLib.addresses.realm_dart_void_completion_callback, - createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ) - .raiseLastErrorIfFalse("Logout failed"); - } else { - realmLib - .realm_app_log_out( - pointer, - user.pointer, - realmLib.addresses.realm_dart_void_completion_callback, - createAsyncCallbackUserdata(completer), - realmLib.addresses.realm_dart_userdata_async_free, - ) - .raiseLastErrorIfFalse("Logout failed"); - } - return completer.future; - } - Future deleteUser(UserHandle user) { final completer = Completer(); realmLib @@ -311,11 +284,11 @@ class AppHandle extends HandleBase { createAsyncCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseLastErrorIfFalse("Delete user failed"); + .raiseLastErrorIfFalse(); return completer.future; } - bool immediatelyRunFileActions(String realmPath) { + bool resetRealm(String realmPath) { return using((arena) { final didRun = arena(); realmLib @@ -324,7 +297,7 @@ class AppHandle extends HandleBase { realmPath.toCharPtr(arena), didRun, ) - .raiseLastErrorIfFalse("An error occurred while resetting the Realm. Check if the file is in use: '$realmPath'"); + .raiseLastErrorIfFalse(); return didRun.value; }); } @@ -349,152 +322,6 @@ class AppHandle extends HandleBase { } } -// TODO: -// We need a pure Dart equivalent of: -// ```dart -// ServiceBinding.rootIsolateToken != null -// ``` -// to get rid of this hack. -final bool _isRootIsolate = Isolate.current.debugName == 'main'; - -class _HttpTransportHandle extends HandleBase { - _HttpTransportHandle(Pointer pointer) : super(pointer, 24); -} - -_HttpTransportHandle _createHttpTransport(HttpClient httpClient) { - final requestCallback = Pointer.fromFunction)>(_requestCallback); - final requestCallbackUserdata = realmLib.realm_dart_userdata_async_new(httpClient, requestCallback.cast(), scheduler.handle.pointer); - return _HttpTransportHandle(realmLib.realm_http_transport_new( - realmLib.addresses.realm_dart_http_request_callback, - requestCallbackUserdata.cast(), - realmLib.addresses.realm_dart_userdata_async_free, - )); -} - -void _requestCallback(Object userData, realm_http_request request, Pointer requestContext) { - // - // The request struct only survives until end-of-call, even though - // we explicitly call realm_http_transport_complete_request to - // mark request as completed later. - // - // Therefore we need to copy everything out of request before returning. - // We cannot clone request on the native side with realm_clone, - // since realm_http_request does not inherit from WrapC. - - final client = userData as HttpClient; - - client.connectionTimeout = Duration(milliseconds: request.timeout_ms); - - final url = Uri.parse(request.url.cast().toRealmDartString()!); - - final body = request.body.cast().toRealmDartString(length: request.body_size); - - final headers = {}; - for (int i = 0; i < request.num_headers; ++i) { - final header = request.headers[i]; - final name = header.name.cast().toRealmDartString()!; - final value = header.value.cast().toRealmDartString()!; - headers[name] = value; - } - - _requestCallbackAsync(client, request.method, url, body, headers, requestContext); - // The request struct dies here! -} - -Future _requestCallbackAsync( - HttpClient client, - int requestMethod, - Uri url, - String? body, - Map headers, - Pointer requestContext, -) async { - await using((arena) async { - final responsePointer = arena(); - final responseRef = responsePointer.ref; - final method = HttpMethod.values[requestMethod]; - - try { - // Build request - late HttpClientRequest request; - - switch (method) { - case HttpMethod.delete: - request = await client.deleteUrl(url); - break; - case HttpMethod.put: - request = await client.putUrl(url); - break; - case HttpMethod.patch: - request = await client.patchUrl(url); - break; - case HttpMethod.post: - request = await client.postUrl(url); - break; - case HttpMethod.get: - request = await client.getUrl(url); - break; - } - - for (final header in headers.entries) { - request.headers.add(header.key, header.value); - } - - if (body != null) { - request.add(utf8.encode(body)); - } - - Realm.logger.log(LogLevel.debug, "HTTP Transport: Executing ${method.name} $url"); - - final stopwatch = Stopwatch()..start(); - - // Do the call.. - final response = await request.close(); - - stopwatch.stop(); - Realm.logger.log(LogLevel.debug, "HTTP Transport: Executed ${method.name} $url: ${response.statusCode} in ${stopwatch.elapsedMilliseconds} ms"); - - final responseBody = await response.fold>([], (acc, l) => acc..addAll(l)); // gather response - - // Report back to core - responseRef.status_code = response.statusCode; - responseRef.body = responseBody.toCharPtr(arena); - responseRef.body_size = responseBody.length; - - int headerCnt = 0; - response.headers.forEach((name, values) { - headerCnt += values.length; - }); - - responseRef.headers = arena(headerCnt); - responseRef.num_headers = headerCnt; - - int index = 0; - response.headers.forEach((name, values) { - for (final value in values) { - final headerRef = (responseRef.headers + index).ref; - headerRef.name = name.toCharPtr(arena); - headerRef.value = value.toCharPtr(arena); - index++; - } - }); - - responseRef.custom_status_code = CustomErrorCode.noError.code; - } on SocketException catch (socketEx) { - Realm.logger.log(LogLevel.warn, "HTTP Transport: SocketException executing ${method.name} $url: $socketEx"); - responseRef.custom_status_code = CustomErrorCode.timeout.code; - } on HttpException catch (httpEx) { - Realm.logger.log(LogLevel.warn, "HTTP Transport: HttpException executing ${method.name} $url: $httpEx"); - responseRef.custom_status_code = CustomErrorCode.unknownHttp.code; - } catch (ex) { - Realm.logger.log(LogLevel.error, "HTTP Transport: Exception executing ${method.name} $url: $ex"); - responseRef.custom_status_code = CustomErrorCode.unknown.code; - } finally { - realmLib.realm_http_transport_complete_request(requestContext, responsePointer); - } - }); -} - Pointer createAsyncFunctionCallbackUserdata(Completer completer) { final callback = Pointer.fromFunction< Void Function( @@ -524,7 +351,7 @@ void _callAppFunctionCallback(Pointer userdata, Pointer response, Po completer.complete(stringResponse); } -Pointer createAsyncCallbackUserdata(Completer completer) { +Pointer createAsyncCallbackUserdata(Completer completer) { final callback = Pointer.fromFunction< Void Function( Pointer, @@ -555,7 +382,7 @@ class _AppConfigHandle extends HandleBase { _AppConfigHandle(Pointer pointer) : super(pointer, 8); } -_AppConfigHandle _createAppConfig(AppConfiguration configuration, _HttpTransportHandle httpTransport) { +_AppConfigHandle _createAppConfig(AppConfiguration configuration, HttpTransportHandle httpTransport) { return using((arena) { final appId = configuration.appId.toCharPtr(arena); final handle = _AppConfigHandle(realmLib.realm_app_config_new(appId, httpTransport.pointer)); @@ -590,3 +417,11 @@ _AppConfigHandle _createAppConfig(AppConfiguration configuration, _HttpTransport return handle; }); } + +// TODO: +// We need a pure Dart equivalent of: +// ```dart +// ServiceBinding.rootIsolateToken != null +// ``` +// to get rid of this hack. +final bool _isRootIsolate = Isolate.current.debugName == 'main'; diff --git a/packages/realm_dart/lib/src/native/async_open_task_handle.dart b/packages/realm_dart/lib/src/native/async_open_task_handle.dart index 483461231..ddd184276 100644 --- a/packages/realm_dart/lib/src/native/async_open_task_handle.dart +++ b/packages/realm_dart/lib/src/native/async_open_task_handle.dart @@ -18,7 +18,7 @@ class AsyncOpenTaskHandle extends HandleBase { factory AsyncOpenTaskHandle.from(FlexibleSyncConfiguration config) { final configHandle = ConfigHandle.from(config); - final asyncOpenTaskPtr = realmLib.realm_open_synchronized(configHandle.pointer)..raiseLastErrorIfNull("Error opening realm at path ${config.path}"); + final asyncOpenTaskPtr = realmLib.realm_open_synchronized(configHandle.pointer).raiseLastErrorIfNull(); return AsyncOpenTaskHandle(asyncOpenTaskPtr); } diff --git a/packages/realm_dart/lib/src/native/collection_handle_base.dart b/packages/realm_dart/lib/src/native/collection_handle_base.dart new file mode 100644 index 000000000..762ee33a5 --- /dev/null +++ b/packages/realm_dart/lib/src/native/collection_handle_base.dart @@ -0,0 +1,51 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + +import 'dart:ffi'; + +import 'package:realm_dart/src/native/rooted_handle.dart'; + +import '../realm_class.dart'; +import 'list_handle.dart'; +import 'map_handle.dart'; +import 'realm_bindings.dart'; + +abstract class CollectionHandleBase extends RootedHandleBase { + CollectionHandleBase(super.root, super.pointer, super.size); +} + +void createCollection(Realm realm, RealmValue value, Pointer Function() createList, Pointer Function() createMap) { + CollectionHandleBase? collectionHandle; + try { + switch (value.collectionType) { + case RealmCollectionType.list: + final listHandle = ListHandle(createList(), realm.handle); + collectionHandle = listHandle; + + final list = realm.createList(listHandle, null); + + // Necessary since Core will not clear the collection if the value was already a collection + list.clear(); + + for (final item in value.value as List) { + list.add(item); + } + case RealmCollectionType.map: + final mapHandle = MapHandle(createMap(), realm.handle); + collectionHandle = mapHandle; + + final map = realm.createMap(mapHandle, null); + + // Necessary since Core will not clear the collection if the value was already a collection + map.clear(); + + for (final kvp in (value.value as Map).entries) { + map[kvp.key] = kvp.value; + } + default: + throw RealmStateError('_createCollection invoked with type that is not list or map.'); + } + } finally { + collectionHandle?.release(); + } +} diff --git a/packages/realm_dart/lib/src/native/config_handle.dart b/packages/realm_dart/lib/src/native/config_handle.dart index efa62208a..eb5fecafe 100644 --- a/packages/realm_dart/lib/src/native/config_handle.dart +++ b/packages/realm_dart/lib/src/native/config_handle.dart @@ -88,7 +88,7 @@ class ConfigHandle extends HandleBase { realmLib.realm_config_set_in_memory(configHandle.pointer, true); } else if (config is FlexibleSyncConfiguration) { realmLib.realm_config_set_schema_mode(configHandle.pointer, realm_schema_mode.RLM_SCHEMA_MODE_ADDITIVE_DISCOVERED); - final syncConfigPtr = realmLib.realm_flx_sync_config_new(config.user.handle.pointer)..raiseLastErrorIfNull(); + final syncConfigPtr = realmLib.realm_flx_sync_config_new(config.user.handle.pointer).raiseLastErrorIfNull(); try { realmLib.realm_sync_config_set_session_stop_policy(syncConfigPtr, config.sessionStopPolicy.index); realmLib.realm_sync_config_set_resync_mode(syncConfigPtr, config.clientResetHandler.clientResyncMode.index); @@ -168,7 +168,8 @@ void _syncAfterResetCallback(Object userdata, Pointer beforeHandle ))); try { - return await afterResetCallback(beforeRealm, afterRealm); + await afterResetCallback(beforeRealm, afterRealm); + return; } finally { beforeRealm.handle.release(); afterRealm.handle.release(); diff --git a/packages/realm_dart/lib/src/native/error_handling.dart b/packages/realm_dart/lib/src/native/error_handling.dart index f6be123cb..68f47fea8 100644 --- a/packages/realm_dart/lib/src/native/error_handling.dart +++ b/packages/realm_dart/lib/src/native/error_handling.dart @@ -11,17 +11,18 @@ import 'realm_bindings.dart'; import 'realm_library.dart'; extension PointerEx on Pointer { - void raiseLastErrorIfNull([String? message]) { + Pointer raiseLastErrorIfNull() { if (this == nullptr) { - raiseLastError(message); + _raiseLastError(); } + return this; } } extension BoolEx on bool { - void raiseLastErrorIfFalse([String? message]) { + void raiseLastErrorIfFalse() { if (!this) { - raiseLastError(message); + _raiseLastError(); } } } @@ -37,17 +38,15 @@ class LastError { String toString() => "${message ?? 'No message'}. Error code: $code."; } -LastError? getLastError(Allocator allocator) { +LastError? _getLastError(Allocator allocator) { final error = allocator(); final success = realmLib.realm_get_last_error(error); return success ? error.ref.toDart() : null; } -Never raiseLastError([String? errorMessage]) { +Never _raiseLastError([String? errorMessage]) { using((arena) { - final lastError = getLastError(arena); - //raise(lastError); - + final lastError = _getLastError(arena); if (lastError?.userError != null) { throw UserCallbackException(lastError!.userError!); } diff --git a/packages/realm_dart/lib/src/native/http_transport_handle.dart b/packages/realm_dart/lib/src/native/http_transport_handle.dart new file mode 100644 index 000000000..afb776bfd --- /dev/null +++ b/packages/realm_dart/lib/src/native/http_transport_handle.dart @@ -0,0 +1,153 @@ +// Copyright 2024 MongoDB, Inc. +// SPDX-License-Identifier: Apache-2.0 + +import 'dart:convert'; +import 'dart:ffi'; +import 'dart:io'; + +import '../logging.dart'; +import '../realm_dart.dart'; +import '../scheduler.dart'; +import 'convert_native.dart'; +import 'ffi.dart'; +import 'handle_base.dart'; +import 'realm_bindings.dart'; +import 'realm_library.dart'; + +class HttpTransportHandle extends HandleBase { + HttpTransportHandle(Pointer pointer) : super(pointer, 24); + + factory HttpTransportHandle.from(HttpClient httpClient) { + final requestCallback = Pointer.fromFunction)>(_requestCallback); + final requestCallbackUserdata = realmLib.realm_dart_userdata_async_new(httpClient, requestCallback.cast(), scheduler.handle.pointer); + return HttpTransportHandle(realmLib.realm_http_transport_new( + realmLib.addresses.realm_dart_http_request_callback, + requestCallbackUserdata.cast(), + realmLib.addresses.realm_dart_userdata_async_free, + )); + } +} + +void _requestCallback(Object userData, realm_http_request request, Pointer requestContext) { + // + // The request struct only survives until end-of-call, even though + // we explicitly call realm_http_transport_complete_request to + // mark request as completed later. + // + // Therefore we need to copy everything out of request before returning. + // We cannot clone request on the native side with realm_clone, + // since realm_http_request does not inherit from WrapC. + + final client = userData as HttpClient; + + client.connectionTimeout = Duration(milliseconds: request.timeout_ms); + + final url = Uri.parse(request.url.cast().toRealmDartString()!); + + final body = request.body.cast().toRealmDartString(length: request.body_size); + + final headers = {}; + for (int i = 0; i < request.num_headers; ++i) { + final header = request.headers[i]; + final name = header.name.cast().toRealmDartString()!; + final value = header.value.cast().toRealmDartString()!; + headers[name] = value; + } + + _requestCallbackAsync(client, request.method, url, body, headers, requestContext); + // The request struct dies here! +} + +Future _requestCallbackAsync( + HttpClient client, + int requestMethod, + Uri url, + String? body, + Map headers, + Pointer requestContext, +) async { + await using((arena) async { + final responsePointer = arena(); + final responseRef = responsePointer.ref; + final method = HttpMethod.values[requestMethod]; + + try { + // Build request + late HttpClientRequest request; + + switch (method) { + case HttpMethod.delete: + request = await client.deleteUrl(url); + break; + case HttpMethod.put: + request = await client.putUrl(url); + break; + case HttpMethod.patch: + request = await client.patchUrl(url); + break; + case HttpMethod.post: + request = await client.postUrl(url); + break; + case HttpMethod.get: + request = await client.getUrl(url); + break; + } + + for (final header in headers.entries) { + request.headers.add(header.key, header.value); + } + + if (body != null) { + request.add(utf8.encode(body)); + } + + Realm.logger.log(LogLevel.debug, "HTTP Transport: Executing ${method.name} $url"); + + final stopwatch = Stopwatch()..start(); + + // Do the call.. + final response = await request.close(); + + stopwatch.stop(); + Realm.logger.log(LogLevel.debug, "HTTP Transport: Executed ${method.name} $url: ${response.statusCode} in ${stopwatch.elapsedMilliseconds} ms"); + + final responseBody = await response.fold>([], (acc, l) => acc..addAll(l)); // gather response + + // Report back to core + responseRef.status_code = response.statusCode; + responseRef.body = responseBody.toCharPtr(arena); + responseRef.body_size = responseBody.length; + + int headerCnt = 0; + response.headers.forEach((name, values) { + headerCnt += values.length; + }); + + responseRef.headers = arena(headerCnt); + responseRef.num_headers = headerCnt; + + int index = 0; + response.headers.forEach((name, values) { + for (final value in values) { + final headerRef = (responseRef.headers + index).ref; + headerRef.name = name.toCharPtr(arena); + headerRef.value = value.toCharPtr(arena); + index++; + } + }); + + responseRef.custom_status_code = CustomErrorCode.noError.code; + } on SocketException catch (socketEx) { + Realm.logger.log(LogLevel.warn, "HTTP Transport: SocketException executing ${method.name} $url: $socketEx"); + responseRef.custom_status_code = CustomErrorCode.timeout.code; + } on HttpException catch (httpEx) { + Realm.logger.log(LogLevel.warn, "HTTP Transport: HttpException executing ${method.name} $url: $httpEx"); + responseRef.custom_status_code = CustomErrorCode.unknownHttp.code; + } catch (ex) { + Realm.logger.log(LogLevel.error, "HTTP Transport: Exception executing ${method.name} $url: $ex"); + responseRef.custom_status_code = CustomErrorCode.unknown.code; + } finally { + realmLib.realm_http_transport_complete_request(requestContext, responsePointer); + } + }); +} diff --git a/packages/realm_dart/lib/src/native/list_handle.dart b/packages/realm_dart/lib/src/native/list_handle.dart index 66f265ebd..5021b5abc 100644 --- a/packages/realm_dart/lib/src/native/list_handle.dart +++ b/packages/realm_dart/lib/src/native/list_handle.dart @@ -4,6 +4,7 @@ import 'dart:ffi'; import '../realm_dart.dart'; +import 'collection_handle_base.dart'; import 'convert_native.dart'; import 'error_handling.dart'; import 'ffi.dart'; @@ -14,7 +15,6 @@ import 'realm_bindings.dart'; import 'realm_handle.dart'; import 'realm_library.dart'; import 'results_handle.dart'; -import 'rooted_handle.dart'; class ListHandle extends CollectionHandleBase { ListHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 88); diff --git a/packages/realm_dart/lib/src/native/map_handle.dart b/packages/realm_dart/lib/src/native/map_handle.dart index 66ca44cfb..27a96402a 100644 --- a/packages/realm_dart/lib/src/native/map_handle.dart +++ b/packages/realm_dart/lib/src/native/map_handle.dart @@ -3,21 +3,19 @@ import 'dart:ffi'; -import 'ffi.dart'; - import '../realm_dart.dart'; +import 'collection_handle_base.dart'; import 'convert_native.dart'; import 'error_handling.dart'; +import 'ffi.dart'; import 'map_changes_handle.dart'; import 'notification_token_handle.dart'; import 'object_handle.dart'; import 'query_handle.dart'; import 'realm_bindings.dart'; -// TODO: remove this import import 'realm_handle.dart'; import 'realm_library.dart'; import 'results_handle.dart'; -import 'rooted_handle.dart'; class MapHandle extends CollectionHandleBase { MapHandle(Pointer pointer, RealmHandle root) : super(root, pointer, 96); // TODO: check size diff --git a/packages/realm_dart/lib/src/native/object_handle.dart b/packages/realm_dart/lib/src/native/object_handle.dart index 9e1277a56..f561e1815 100644 --- a/packages/realm_dart/lib/src/native/object_handle.dart +++ b/packages/realm_dart/lib/src/native/object_handle.dart @@ -3,11 +3,11 @@ import 'dart:ffi'; -import 'ffi.dart'; - import '../realm_dart.dart'; +import 'collection_handle_base.dart'; import 'convert_native.dart'; import 'error_handling.dart'; +import 'ffi.dart'; import 'handle_base.dart'; import 'list_handle.dart'; import 'map_handle.dart'; @@ -147,7 +147,7 @@ class ObjectHandle extends RootedHandleBase { } // TODO(kn): // call to classKey getter involves a native call, which is not ideal - return realmLib.realm_create_key_path_array(root.pointer, classKey, length, keypathsNative)..raiseLastErrorIfNull(); + return realmLib.realm_create_key_path_array(root.pointer, classKey, length, keypathsNative).raiseLastErrorIfNull(); }); } diff --git a/packages/realm_dart/lib/src/native/realm_core.dart b/packages/realm_dart/lib/src/native/realm_core.dart index 7c095fec4..a05b4d1ab 100644 --- a/packages/realm_dart/lib/src/native/realm_core.dart +++ b/packages/realm_dart/lib/src/native/realm_core.dart @@ -42,7 +42,7 @@ final _pluginLib = () { class RealmCore { RealmCore._(); - + // For debugging int get threadId => realmLib.realm_dart_get_thread_id(); @@ -58,7 +58,7 @@ class RealmCore { void deleteRealmFiles(String path) { using((arena) { final realmDeleted = arena(); - realmLib.realm_delete_files(path.toCharPtr(arena), realmDeleted).raiseLastErrorIfFalse("Error deleting realm at path $path"); + realmLib.realm_delete_files(path.toCharPtr(arena), realmDeleted).raiseLastErrorIfFalse(); }); } @@ -134,7 +134,7 @@ class RealmCore { const salt = [82, 101, 97, 108, 109, 32, 105, 115, 32, 103, 114, 101, 97, 116]; return base64Encode(sha256.convert([...salt, ...utf8.encode(bundleId)]).bytes); } - + String getDefaultBaseUrl() { return realmLib.realm_app_get_default_base_url().cast().toRealmDartString()!; } diff --git a/packages/realm_dart/lib/src/native/realm_handle.dart b/packages/realm_dart/lib/src/native/realm_handle.dart index fe5a94001..91a4ac925 100644 --- a/packages/realm_dart/lib/src/native/realm_handle.dart +++ b/packages/realm_dart/lib/src/native/realm_handle.dart @@ -36,8 +36,9 @@ class RealmHandle extends HandleBase { factory RealmHandle.open(Configuration config) { final configHandle = ConfigHandle.from(config); - return RealmHandle(realmLib.realm_open(configHandle.pointer) // - ..raiseLastErrorIfNull('Error opening realm at path ${config.path}')); + return RealmHandle(realmLib + .realm_open(configHandle.pointer) // + .raiseLastErrorIfNull()); } int addChild(RootedHandleBase child) { @@ -144,7 +145,7 @@ class RealmHandle extends HandleBase { } void close() { - realmLib.realm_close(pointer).raiseLastErrorIfFalse("Realm close failed"); + realmLib.realm_close(pointer).raiseLastErrorIfFalse(); } bool get isClosed { @@ -152,11 +153,11 @@ class RealmHandle extends HandleBase { } void beginWrite() { - realmLib.realm_begin_write(pointer).raiseLastErrorIfFalse("Could not begin write"); + realmLib.realm_begin_write(pointer).raiseLastErrorIfFalse(); } void commitWrite() { - realmLib.realm_commit(pointer).raiseLastErrorIfFalse("Could not commit write"); + realmLib.realm_commit(pointer).raiseLastErrorIfFalse(); } Future beginWriteAsync(CancellationToken? ct) { @@ -238,13 +239,13 @@ class RealmHandle extends HandleBase { } void rollbackWrite() { - realmLib.realm_rollback(pointer).raiseLastErrorIfFalse("Could not rollback write"); + realmLib.realm_rollback(pointer).raiseLastErrorIfFalse(); } bool refresh() { return using((arena) { final didRefresh = arena(); - realmLib.realm_refresh(pointer, didRefresh).raiseLastErrorIfFalse("Could not refresh"); + realmLib.realm_refresh(pointer, didRefresh).raiseLastErrorIfFalse(); return didRefresh.value; }); } @@ -252,15 +253,13 @@ class RealmHandle extends HandleBase { Future refreshAsync() async { final completer = Completer(); final callback = Pointer.fromFunction)>(_realmRefreshAsyncCallback); - Pointer completerPtr = realmLib.realm_dart_object_to_persistent_handle(completer); - Pointer result = - realmLib.realm_add_realm_refresh_callback(pointer, callback.cast(), completerPtr, realmLib.addresses.realm_dart_delete_persistent_handle); + final completerPtr = realmLib.realm_dart_object_to_persistent_handle(completer); + final result = realmLib.realm_add_realm_refresh_callback(pointer, callback.cast(), completerPtr, realmLib.addresses.realm_dart_delete_persistent_handle); if (result == nullptr) { - return Future.value(false); + return false; } - - return completer.future; + return await completer.future; } static void _realmRefreshAsyncCallback(Pointer userdata) { @@ -409,12 +408,6 @@ class RealmHandle extends HandleBase { final found = arena(); final classInfo = arena(); realmLib.realm_find_class(pointer, schema.name.toCharPtr(arena), found, classInfo).raiseLastErrorIfFalse(); - // "Error getting class ${schema.name} from realm at ${realm.config.path}"); - - if (!found.value) { - raiseLastError(); //"Class ${schema.name} not found in ${realm.config.path}"); - } - final primaryKey = classInfo.ref.primary_key.cast().toRealmDartString(treatEmptyAsNull: true); return RealmObjectMetadata(schema, classInfo.ref.key, _getPropertiesMetadata(classInfo.ref.key, primaryKey, arena)); }); @@ -422,13 +415,11 @@ class RealmHandle extends HandleBase { Map _getPropertiesMetadata(int classKey, String? primaryKeyName, Arena arena) { final propertyCountPtr = arena(); - realmLib.realm_get_property_keys(pointer, classKey, nullptr, 0, propertyCountPtr).raiseLastErrorIfFalse("Error getting property count"); + realmLib.realm_get_property_keys(pointer, classKey, nullptr, 0, propertyCountPtr).raiseLastErrorIfFalse(); var propertyCount = propertyCountPtr.value; final propertiesPtr = arena(propertyCount); - realmLib - .realm_get_class_properties(pointer, classKey, propertiesPtr, propertyCount, propertyCountPtr) - .raiseLastErrorIfFalse("Error getting class properties."); + realmLib.realm_get_class_properties(pointer, classKey, propertiesPtr, propertyCount, propertyCountPtr).raiseLastErrorIfFalse(); propertyCount = propertyCountPtr.value; Map result = {}; diff --git a/packages/realm_dart/lib/src/native/rooted_handle.dart b/packages/realm_dart/lib/src/native/rooted_handle.dart index 85ba4efaf..810961885 100644 --- a/packages/realm_dart/lib/src/native/rooted_handle.dart +++ b/packages/realm_dart/lib/src/native/rooted_handle.dart @@ -3,11 +3,7 @@ import 'dart:ffi'; -import '../realm_class.dart'; import 'handle_base.dart'; -import 'list_handle.dart'; -import 'map_handle.dart'; -import 'realm_bindings.dart'; import 'realm_handle.dart'; class FinalizationToken { @@ -43,43 +39,3 @@ abstract class RootedHandleBase extends HandleBase { } } } - -abstract class CollectionHandleBase extends RootedHandleBase { - CollectionHandleBase(super.root, super.pointer, super.size); -} - -void createCollection(Realm realm, RealmValue value, Pointer Function() createList, Pointer Function() createMap) { - CollectionHandleBase? collectionHandle; - try { - switch (value.collectionType) { - case RealmCollectionType.list: - final listHandle = ListHandle(createList(), realm.handle); - collectionHandle = listHandle; - - final list = realm.createList(listHandle, null); - - // Necessary since Core will not clear the collection if the value was already a collection - list.clear(); - - for (final item in value.value as List) { - list.add(item); - } - case RealmCollectionType.map: - final mapHandle = MapHandle(createMap(), realm.handle); - collectionHandle = mapHandle; - - final map = realm.createMap(mapHandle, null); - - // Necessary since Core will not clear the collection if the value was already a collection - map.clear(); - - for (final kvp in (value.value as Map).entries) { - map[kvp.key] = kvp.value; - } - default: - throw RealmStateError('_createCollection invoked with type that is not list or map.'); - } - } finally { - collectionHandle?.release(); - } -} diff --git a/packages/realm_dart/lib/src/native/to_native.dart b/packages/realm_dart/lib/src/native/to_native.dart index 5a6fd7ec0..5497146fc 100644 --- a/packages/realm_dart/lib/src/native/to_native.dart +++ b/packages/realm_dart/lib/src/native/to_native.dart @@ -2,6 +2,8 @@ import 'dart:convert'; import 'dart:ffi'; import 'dart:typed_data'; +import 'package:realm_dart/src/native/realm_library.dart'; + import '../realm_dart.dart'; import '../realm_object.dart'; import 'decimal128.dart'; @@ -42,8 +44,7 @@ extension NullableObjectEx on Object? { final self = this; final realmValue = allocator(); if (self is RealmValue && self.type.isCollection) { - throw RealmError( - "Don't use _toPrimitiveValue if the value may contain collections. Use storeValue instead. This is a bug in the Realm Flutter SDK and should be reported to https://github.com/realm/realm-dart/issues/new"); + throw RealmError("Don't use toNative if the value may contain collections. $bugInTheSdkMessage"); } _intoRealmValue(self, realmValue.ref, allocator); return realmValue; diff --git a/packages/realm_dart/lib/src/native/user_handle.dart b/packages/realm_dart/lib/src/native/user_handle.dart index 8b9806cbb..1092a0143 100644 --- a/packages/realm_dart/lib/src/native/user_handle.dart +++ b/packages/realm_dart/lib/src/native/user_handle.dart @@ -34,7 +34,7 @@ class UserHandle extends HandleBase { } String get id { - final idPtr = realmLib.realm_user_get_identity(pointer)..raiseLastErrorIfNull("Error while getting user id"); + final idPtr = realmLib.realm_user_get_identity(pointer).raiseLastErrorIfNull(); final userId = idPtr.cast().toDartString(); return userId; } @@ -68,32 +68,32 @@ class UserHandle extends HandleBase { } Future logOut() async { - realmLib.realm_user_log_out(pointer).raiseLastErrorIfFalse("Logout failed"); + realmLib.realm_user_log_out(pointer).raiseLastErrorIfFalse(); } String? get deviceId { - final deviceId = realmLib.realm_user_get_device_id(pointer)..raiseLastErrorIfNull(); + final deviceId = realmLib.realm_user_get_device_id(pointer).raiseLastErrorIfNull(); return deviceId.cast().toRealmDartString(treatEmptyAsNull: true, freeRealmMemory: true); } UserProfile get profileData { - final data = realmLib.realm_user_get_profile_data(pointer)..raiseLastErrorIfNull(); + final data = realmLib.realm_user_get_profile_data(pointer).raiseLastErrorIfNull(); final dynamic profileData = jsonDecode(data.cast().toRealmDartString(freeRealmMemory: true)!); return UserProfile(profileData as Map); } String get refreshToken { - final token = realmLib.realm_user_get_refresh_token(pointer)..raiseLastErrorIfNull(); + final token = realmLib.realm_user_get_refresh_token(pointer).raiseLastErrorIfNull(); return token.cast().toRealmDartString(freeRealmMemory: true)!; } String get accessToken { - final token = realmLib.realm_user_get_access_token(pointer)..raiseLastErrorIfNull(); + final token = realmLib.realm_user_get_access_token(pointer).raiseLastErrorIfNull(); return token.cast().toRealmDartString(freeRealmMemory: true)!; } String get path { - final syncConfigPtr = realmLib.realm_flx_sync_config_new(pointer)..raiseLastErrorIfNull(); + final syncConfigPtr = realmLib.realm_flx_sync_config_new(pointer).raiseLastErrorIfNull(); try { final path = realmLib.realm_app_sync_client_get_default_file_path_for_realm(syncConfigPtr, nullptr); return path.cast().toRealmDartString(freeRealmMemory: true)!; @@ -118,7 +118,7 @@ class UserHandle extends HandleBase { createAsyncUserCallbackUserdata(completer), realmLib.addresses.realm_dart_userdata_async_free, ) - .raiseLastErrorIfFalse("Link credentials failed"); + .raiseLastErrorIfFalse(); return completer.future; } diff --git a/packages/realm_dart/test/app_test.dart b/packages/realm_dart/test/app_test.dart index b543c0946..9dd41f46e 100644 --- a/packages/realm_dart/test/app_test.dart +++ b/packages/realm_dart/test/app_test.dart @@ -299,7 +299,7 @@ void main() { expect(app.currentUser, user2); expect( () => app.switchUser(user1), - throws("Switch user failed. User is no longer valid or is logged out"), + throws("User is no longer valid or is logged out"), ); }); diff --git a/packages/realm_dart/test/baas_helper.dart b/packages/realm_dart/test/baas_helper.dart index d35874125..52a5a368b 100644 --- a/packages/realm_dart/test/baas_helper.dart +++ b/packages/realm_dart/test/baas_helper.dart @@ -151,9 +151,9 @@ class BaasHelper { } } - Future createServerApiKey(App app, String name, {bool enabled = true}) async { + Future createServerApiKey(App app, String name, {bool enabled = true}) { final baasApp = _baasApps.values.firstWhere((ba) => ba.clientAppId == app.id); - return await _baasClient.createApiKey(baasApp.appId, name, enabled); + return _baasClient.createApiKey(baasApp.appId, name, enabled); } static void throwIfSetupFailed() { From fe9227b5c66bc2fd1827759b26ba2476677ab22f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Mon, 13 May 2024 09:57:58 +0200 Subject: [PATCH 64/68] Fix rebase --- packages/realm_dart/lib/src/realm_class.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/realm_dart/lib/src/realm_class.dart b/packages/realm_dart/lib/src/realm_class.dart index 8c80c79df..a337ad27e 100644 --- a/packages/realm_dart/lib/src/realm_class.dart +++ b/packages/realm_dart/lib/src/realm_class.dart @@ -984,19 +984,19 @@ class DynamicRealm { RealmObject create(String className, {Object? primaryKey}) { final metadata = _realm._metadata.getByName(className); - RealmObjectHandle handle; + ObjectHandle handle; if (metadata.primaryKey != null) { if (primaryKey == null) { throw RealmError("The class $className has primary key defined, but you didn't pass one"); } - handle = realmCore.createRealmObjectWithPrimaryKey(_realm, metadata.classKey, primaryKey); + handle = _realm._handle.createWithPrimaryKey(metadata.classKey, primaryKey); } else { if (primaryKey != null) { throw RealmError("The class $className doesn't have primary key defined, but you passed $primaryKey"); } - handle = realmCore.createRealmObject(_realm, metadata.classKey); + handle = _realm._handle.create(metadata.classKey); } final accessor = RealmCoreAccessor(metadata, _realm._isInMigration); From 8ee2b31b33216b3f304ddd845050b6be2d0ad9a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Thu, 23 May 2024 09:32:03 +0200 Subject: [PATCH 65/68] Tweat memEquals perf test --- packages/realm_dart/test/realm_value_test.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/realm_dart/test/realm_value_test.dart b/packages/realm_dart/test/realm_value_test.dart index 4b3b6b4ff..eb679f203 100644 --- a/packages/realm_dart/test/realm_value_test.dart +++ b/packages/realm_dart/test/realm_value_test.dart @@ -2454,7 +2454,8 @@ void main() { expect(RealmValue.from(bin1), isNot(RealmValue.from(bin2))); } - // Not quite 8 times speedup, but close enough. - expect(listEqualsClock.elapsedTicks ~/ 5, greaterThan(memEqualsClock.elapsedTicks)); + // Not quite 8 times speedup, but close enough. Setting the threshold to 4 + // for test stability sake. + expect(listEqualsClock.elapsedTicks ~/ 4, greaterThan(memEqualsClock.elapsedTicks)); }); } From fe7d582c9a8c3c0f1502858522920ff846a3765d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Thu, 23 May 2024 11:37:27 +0200 Subject: [PATCH 66/68] fixup! Last leg.. for now --- packages/realm_dart/lib/src/scheduler.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/realm_dart/lib/src/scheduler.dart b/packages/realm_dart/lib/src/scheduler.dart index 104cb1af1..af9c9cbea 100644 --- a/packages/realm_dart/lib/src/scheduler.dart +++ b/packages/realm_dart/lib/src/scheduler.dart @@ -1,6 +1,7 @@ // Copyright 2022 MongoDB, Inc. // SPDX-License-Identifier: Apache-2.0 +import 'dart:async'; import 'dart:ffi'; import 'dart:isolate'; From 4e75f51439a8a5076f5d8968b055976a8e17a2fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Thu, 23 May 2024 11:49:52 +0200 Subject: [PATCH 67/68] Fix after rebase --- packages/realm_dart/lib/src/scheduler.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/realm_dart/lib/src/scheduler.dart b/packages/realm_dart/lib/src/scheduler.dart index af9c9cbea..8c60f1ebe 100644 --- a/packages/realm_dart/lib/src/scheduler.dart +++ b/packages/realm_dart/lib/src/scheduler.dart @@ -45,7 +45,7 @@ class Scheduler { final text = message[2] as String; Realm.logger.raise((category: category, level: level, message: text)); } else if (message is int) { - realmCore.invokeScheduler(message); + handle.invoke(message); } else { Realm.logger.log(LogLevel.error, 'Unexpected Scheduler message type: ${message.runtimeType} - $message'); } From 47fefcc0626503919e28ccf41d6ba2a19bd1f76c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Mon, 27 May 2024 12:25:12 +0200 Subject: [PATCH 68/68] more PR feedback --- packages/realm_dart/lib/src/native/collection_handle_base.dart | 2 +- packages/realm_dart/lib/src/native/config_handle.dart | 1 - packages/realm_dart/lib/src/native/from_native.dart | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/realm_dart/lib/src/native/collection_handle_base.dart b/packages/realm_dart/lib/src/native/collection_handle_base.dart index 762ee33a5..6ac5011c0 100644 --- a/packages/realm_dart/lib/src/native/collection_handle_base.dart +++ b/packages/realm_dart/lib/src/native/collection_handle_base.dart @@ -43,7 +43,7 @@ void createCollection(Realm realm, RealmValue value, Pointer Functio map[kvp.key] = kvp.value; } default: - throw RealmStateError('_createCollection invoked with type that is not list or map.'); + throw RealmStateError('createCollection invoked with type that is not list or map.'); } } finally { collectionHandle?.release(); diff --git a/packages/realm_dart/lib/src/native/config_handle.dart b/packages/realm_dart/lib/src/native/config_handle.dart index eb5fecafe..bb4010a70 100644 --- a/packages/realm_dart/lib/src/native/config_handle.dart +++ b/packages/realm_dart/lib/src/native/config_handle.dart @@ -51,7 +51,6 @@ class ConfigHandle extends HandleBase { realmLib.realm_config_set_max_number_of_active_versions(configHandle.pointer, config.maxNumberOfActiveVersions!); } if (config is LocalConfiguration) { - //realmLib.realm_config_set_schema_mode(configHandle.pointer, realm_schema_mode.RLM_SCHEMA_MODE_ADDITIVE_DISCOVERED); if (config.initialDataCallback != null) { realmLib.realm_config_set_data_initialization_function( configHandle.pointer, diff --git a/packages/realm_dart/lib/src/native/from_native.dart b/packages/realm_dart/lib/src/native/from_native.dart index 9e54d6a53..316331ce2 100644 --- a/packages/realm_dart/lib/src/native/from_native.dart +++ b/packages/realm_dart/lib/src/native/from_native.dart @@ -265,7 +265,7 @@ enum HttpMethod { extension RealmTimestampEx on realm_timestamp_t { DateTime toDart() { - return DateTime.fromMicrosecondsSinceEpoch(seconds * 1000000 + nanoseconds ~/ 1000, isUtc: true); + return DateTime.fromMicrosecondsSinceEpoch(seconds * _microsecondsPerSecond + nanoseconds ~/ 1000, isUtc: true); } }