diff --git a/.vscode/settings.json b/.vscode/settings.json index 1d2133aea..5a4900236 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -63,6 +63,85 @@ "xstring": "cpp", "xutility": "cpp", "iosfwd": "cpp", - "sstream": "cpp" + "sstream": "cpp", + "any": "cpp", + "array": "cpp", + "bit": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "cfenv": "cpp", + "charconv": "cpp", + "cinttypes": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "codecvt": "cpp", + "complex": "cpp", + "condition_variable": "cpp", + "csetjmp": "cpp", + "csignal": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cuchar": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "exception": "cpp", + "forward_list": "cpp", + "future": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "ios": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "list": "cpp", + "locale": "cpp", + "map": "cpp", + "mutex": "cpp", + "new": "cpp", + "numeric": "cpp", + "ostream": "cpp", + "queue": "cpp", + "random": "cpp", + "ratio": "cpp", + "regex": "cpp", + "scoped_allocator": "cpp", + "set": "cpp", + "shared_mutex": "cpp", + "stack": "cpp", + "stdexcept": "cpp", + "stop_token": "cpp", + "streambuf": "cpp", + "string": "cpp", + "thread": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "typeindex": "cpp", + "typeinfo": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "utility": "cpp", + "valarray": "cpp", + "xfacet": "cpp", + "xhash": "cpp", + "xiosbase": "cpp", + "xlocbuf": "cpp", + "xlocinfo": "cpp", + "xlocmes": "cpp", + "xlocnum": "cpp", + "xloctime": "cpp", + "xstddef": "cpp", + "xtr1common": "cpp", + "xtree": "cpp", + "*.tcc": "cpp", + "memory_resource": "cpp", + "string_view": "cpp", + "rope": "cpp", + "slist": "cpp" } } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d31aefe7..1752072d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,14 +2,17 @@ **This project is in the Beta stage. The API should be quite stable, but occasional breaking changes may be made.** +### Breaking Changes +* Fixed an issue that would cause passwords sent to the server (e.g. `Credentials.EmailPassword` or `EmailPasswordAuthProvider.registerUser`) to contain an extra empty byte at the end. (PR [#918](https://github.com/realm/realm-dart/pull/918)). + Notice: Any existing email users might need to be recreated because of this breaking change. + ### Enhancements * Added support for "frozen objects" - these are objects, queries, lists, or Realms that have been "frozen" at a specific version. All frozen objects can be accessed and queried as normal, but attempting to mutate them or add change listeners will throw an exception. `Realm`, `RealmObject`, `RealmList`, and `RealmResults` now have a method `freeze()` which returns an immutable version of the object, as well as an `isFrozen` property which can be used to check whether an object is frozen. ([#56](https://github.com/realm/realm-dart/issues/56)) * You can now set a realm property of type `T` to any object `o` where `o is T`. Previously it was required that `o.runtimeType == T`. ([#904](https://github.com/realm/realm-dart/issues/904)) * Performance of indexOf on realm lists has been improved. It now uses realm-core instead of the generic version from ListMixin. ([#911](https://github.com/realm/realm-dart/pull/911)) * Performance of remove on realm list has been improved. It now uses indexOf and removeAt. ([#915](https://github.com/realm/realm-dart/pull/915)) * Added support for migrations for local Realms. You can now construct a configuration with a migration callback that will be invoked if the schema version of the file on disk is lower than the schema version supplied by the callback. ([#70](https://github.com/realm/realm-dart/issues/70)) - - A minimal example looks like this: + Example: ```dart final config = Configuration.local([Person.schema], schemaVersion: 4, migrationCallback: (migration, oldSchemaVersion) { if (oldSchemaVersion == 1) { @@ -37,20 +40,24 @@ } }); ``` +* Added support for realm list of nullable primitive types, ie. `RealmList`. ([#163](https://github.com/realm/realm-dart/issues/163)) +* Allow null arguments on query. ([#871](https://github.com/realm/realm-dart/issues/871)) ### Fixed -* Allow null arguments on query. ([#871](https://github.com/realm/realm-dart/issues/871)) * Previously removeAt did not truncate length. ([#883](https://github.com/realm/realm-dart/issues/883)) -* List.length= now throws, if you try to increase length, ([#894](https://github.com/realm/realm-dart/pull/894)). +* List.length= now throws, if you try to increase length. This previously succeeded silently. ([#894](https://github.com/realm/realm-dart/pull/894)). * Queries on lists were broken. ([#909](https://github.com/realm/realm-dart/issues/909)) + Example: + ```dart + expect(realm.all(), [alice, bob, carol, dan]); // assume this pass, then ... + expect(team.players.query('TRUEPREDICATE'), [alice, bob]); // <-- ... this fails and return the same as realm.all() + ``` * Queries on results didn't filter the existing results. ([#908](https://github.com/realm/realm-dart/issues/908)). - As an example + Example ```dart - expect(realm.query('FALSEPREDICATE').query('TRUEPREDICATE'), isEmpty); + expect(realm.query('FALSEPREDICATE').query('TRUEPREDICATE'), isEmpty); //<-- Fails if a Persion object exists ``` - would fail if any Persons exists -* Fixed an issue that would cause passwords sent to the server (e.g. `Credentials.EmailPassword` or `EmailPasswordAuthProvider.registerUser`) to contain an extra empty byte at the end. (PR [#918](https://github.com/realm/realm-dart/pull/918)) -* Added support for realm list of nullable primitive types, ie. `RealmList`. ([#163](https://github.com/realm/realm-dart/issues/163)) +* Fixed copying of native structs for session errors and http requests. ([#924](https://github.com/realm/realm-dart/pull/924)) ### Compatibility * Realm Studio: 12.0.0 or later. diff --git a/src/realm_dart_sync.cpp b/src/realm_dart_sync.cpp index 33174a8d5..45eea0548 100644 --- a/src/realm_dart_sync.cpp +++ b/src/realm_dart_sync.cpp @@ -18,35 +18,35 @@ #include #include + #include "realm_dart.hpp" #include "realm_dart_sync.h" -RLM_API void realm_dart_http_request_callback(realm_userdata_t userdata, const realm_http_request_t request, void* request_context) { - // the pointers in error are to stack values, we need to make copies and move them into the scheduler invocation +RLM_API void realm_dart_http_request_callback(realm_userdata_t userdata, realm_http_request_t request, void* request_context) { + // the pointers in request are to stack values, we need to make copies and move them into the scheduler invocation struct request_copy_buf { std::string url; std::string body; - std::map headers; - std::vector headers_vector; + std::vector> headers_values; + std::vector headers; } buf; - realm_http_request_t request_copy = request; // copy struct - buf.url = request.url; - request_copy.url = buf.url.c_str(); buf.body = std::string(request.body, request.body_size); - request_copy.body = buf.body.data(); - - buf.headers_vector.reserve(request.num_headers); + buf.headers_values.reserve(request.num_headers); + buf.headers.reserve(request.num_headers); for (size_t i = 0; i < request.num_headers; i++) { - auto [it, _] = buf.headers.emplace(request.headers[i].name, request.headers[i].value); - buf.headers_vector.push_back({ it->first.c_str(), it->second.c_str() }); + auto& [name, value] = buf.headers_values.emplace_back(request.headers[i].name, request.headers[i].value); + buf.headers.push_back({name.c_str(), value.c_str() }); } - request_copy.headers = buf.headers_vector.data(); auto ud = reinterpret_cast(userdata); - ud->scheduler->invoke([ud, request_copy = std::move(request_copy), buf = std::move(buf), request_context]() { - (reinterpret_cast(ud->dart_callback)(ud->handle, request_copy, request_context)); + ud->scheduler->invoke([ud, request = std::move(request), buf = std::move(buf), request_context]() mutable { + //we moved buf so we need to update the request pointers here. + request.url = buf.url.c_str(); + request.body = buf.body.data(); + request.headers = buf.headers.data(); + (reinterpret_cast(ud->dart_callback)(ud->handle, request, request_context)); }); } @@ -64,25 +64,25 @@ RLM_API void realm_dart_sync_error_handler_callback(realm_userdata_t userdata, r struct error_copy { std::string message; std::string detailed_message; - std::map user_info_map; - std::vector user_info_vector; + std::vector> user_info_values; + std::vector user_info; } buf; buf.message = error.error_code.message; - error.error_code.message = buf.message.c_str(); - buf.detailed_message = error.detailed_message; - error.detailed_message = buf.detailed_message.c_str(); - - buf.user_info_vector.reserve(error.user_info_length); + buf.user_info_values.reserve(error.user_info_length); + buf.user_info.reserve(error.user_info_length); for (size_t i = 0; i < error.user_info_length; i++) { - auto [it, _] = buf.user_info_map.emplace(error.user_info_map[i].key, error.user_info_map[i].value); - buf.user_info_vector.push_back({ it->first.c_str(), it->second.c_str() }); + auto& [key, value] = buf.user_info_values.emplace_back(error.user_info_map[i].key, error.user_info_map[i].value); + buf.user_info.push_back({ key.c_str(), value.c_str() }); } - error.user_info_map = buf.user_info_vector.data(); auto ud = reinterpret_cast(userdata); - ud->scheduler->invoke([ud, session = *session, error = std::move(error), buf = std::move(buf)]() { + ud->scheduler->invoke([ud, session = *session, error = std::move(error), buf = std::move(buf)]() mutable { + //we moved buf so we need to update the error pointers here. + error.error_code.message = buf.message.c_str(); + error.detailed_message = buf.detailed_message.c_str(); + error.user_info_map = buf.user_info.data(); (reinterpret_cast(ud->dart_callback))(ud->handle, const_cast(&session), error); }); } diff --git a/src/realm_dart_sync.h b/src/realm_dart_sync.h index 0c04c63c3..90c50e2aa 100644 --- a/src/realm_dart_sync.h +++ b/src/realm_dart_sync.h @@ -20,7 +20,7 @@ #include -RLM_API void realm_dart_http_request_callback(realm_userdata_t userdata, const realm_http_request_t request, void* request_context); +RLM_API void realm_dart_http_request_callback(realm_userdata_t userdata, realm_http_request_t request, void* request_context); RLM_API void realm_dart_sync_client_log_callback(realm_userdata_t userdata, realm_log_level_e level, const char* message);