Skip to content

Commit

Permalink
RDART-941: Clear collections in mixed when reassigned (#1554)
Browse files Browse the repository at this point in the history
* Clear collections in mixed when reassigned

* Add a few more assertions
  • Loading branch information
nirinchev authored Mar 14, 2024
1 parent 465e3bd commit 9e2285b
Show file tree
Hide file tree
Showing 2 changed files with 191 additions and 0 deletions.
8 changes: 8 additions & 0 deletions packages/realm_dart/lib/src/native/realm_core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3021,6 +3021,10 @@ class _RealmCore {
collectionHandle = listHandle;

final list = realm.createList<RealmValue>(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<RealmValue>) {
list.add(item);
}
Expand All @@ -3030,6 +3034,10 @@ class _RealmCore {
collectionHandle = mapHandle;

final map = realm.createMap<RealmValue>(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<String, RealmValue>).entries) {
map[kvp.key] = kvp.value;
}
Expand Down
183 changes: 183 additions & 0 deletions packages/realm_dart/test/realm_value_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,8 @@ void main() {
expect(obj.oneAny.type, RealmValueType.list);
expectMatches(obj.oneAny, [true, 5.3]);

writeIfNecessary(realm, () => obj.oneAny = RealmValue.from(['foo']));

writeIfNecessary(realm, () => obj.oneAny = RealmValue.from(999));
expectMatches(obj.oneAny, 999);

Expand Down Expand Up @@ -566,13 +568,194 @@ void main() {
expect(obj.oneAny.type, RealmValueType.map);
expectMatches(obj.oneAny, {'bool': true, 'double': 5.3});

writeIfNecessary(realm, () => obj.oneAny = RealmValue.from({'foo': 'bar'}));
expectMatches(obj.oneAny, {'foo': 'bar'});

writeIfNecessary(realm, () => obj.oneAny = RealmValue.from(999));
expectMatches(obj.oneAny, 999);

writeIfNecessary(realm, () => obj.oneAny = RealmValue.from([1.23456789]));
expectMatches(obj.oneAny, [1.23456789]);
});

test('Map inside list when $managedString can be reassigned', () {
final realm = getMixedRealm();
final obj = AnythingGoes(
oneAny: RealmValue.from([
true,
{'foo': 'bar'},
5.3
]));
if (isManaged) {
realm.write(() => realm.add(obj));
}

final list = obj.oneAny.asList();

expect(list[1].type, RealmValueType.map);

writeIfNecessary(realm, () => list[1] = RealmValue.from({'new': 5}));
expectMatches(obj.oneAny, [
true,
{'new': 5},
5.3
]);

writeIfNecessary(realm, () {
list.add(list[1]);
});

expectMatches(obj.oneAny, [
true,
{'new': 5},
5.3,
{'new': 5}
]);

// TODO: Self-assignment - this doesn't work due to https://github.com/realm/realm-core/issues/7422
// writeIfNecessary(realm, () {
// list[1] = list[1];
// });
// expectMatches(obj.oneAny, [
// true,
// {'new': 5},
// 5.3,
// {'new': 5}
// ]);
});

test('Map inside map when $managedString can be reassigned', () {
final realm = getMixedRealm();
final obj = AnythingGoes(
oneAny: RealmValue.from({
'a': 5,
'b': {'foo': 'bar'}
}));

if (isManaged) {
realm.write(() => realm.add(obj));
}

final map = obj.oneAny.asMap();

expect(map['b']!.type, RealmValueType.map);

writeIfNecessary(realm, () => map['b'] = RealmValue.from({'new': 5}));
expectMatches(obj.oneAny, {
'a': 5,
'b': {'new': 5}
});

writeIfNecessary(realm, () {
map['c'] = map['b']!;
});

expectMatches(obj.oneAny, {
'a': 5,
'b': {'new': 5},
'c': {'new': 5},
});

// TODO: Self-assignment - this doesn't work due to https://github.com/realm/realm-core/issues/7422
// writeIfNecessary(realm, () {
// map['a'] = map['a'];
// });
// expectMatches(obj.oneAny, {
// 'a': 5,
// 'b': {'new': 5},
// 'c': {'new': 5},
// });
});

test('List inside list when $managedString can be reassigned', () {
final realm = getMixedRealm();
final obj = AnythingGoes(
oneAny: RealmValue.from([
true,
['foo'],
5.3
]));
if (isManaged) {
realm.write(() => realm.add(obj));
}

final list = obj.oneAny.asList();

expect(list[1].type, RealmValueType.list);

writeIfNecessary(realm, () => list[1] = RealmValue.from([5, true]));
expectMatches(obj.oneAny, [
true,
[5, true],
5.3
]);

writeIfNecessary(realm, () {
list.add(list[1]);
});

expectMatches(obj.oneAny, [
true,
[5, true],
5.3,
[5, true]
]);

// TODO: Self-assignment - this doesn't work due to https://github.com/realm/realm-core/issues/7422
// writeIfNecessary(realm, () {
// list[1] = list[1];
// });
// expectMatches(obj.oneAny, [
// true,
// [5, true],
// 5.3,
// [5, true]
// ]);
});

test('List inside map when $managedString can be reassigned', () {
final realm = getMixedRealm();
final obj = AnythingGoes(
oneAny: RealmValue.from({
'a': 5,
'b': ['foo']
}));

if (isManaged) {
realm.write(() => realm.add(obj));
}

final map = obj.oneAny.asMap();

expect(map['b']!.type, RealmValueType.list);

writeIfNecessary(realm, () => map['b'] = RealmValue.from([999, true]));
expectMatches(obj.oneAny, {
'a': 5,
'b': [999, true]
});

writeIfNecessary(realm, () {
map['c'] = map['b']!;
});

expectMatches(obj.oneAny, {
'a': 5,
'b': [999, true],
'c': [999, true]
});

// TODO: Self-assignment - this doesn't work due to https://github.com/realm/realm-core/issues/7422
// writeIfNecessary(realm, () {
// map['a'] = map['a'];
// });
// expectMatches(obj.oneAny, {
// 'a': 5,
// 'b': [999, true],
// 'c': [999, true]
// });
});

test('RealmValue when $managedString can store complex struct', () {
final realm = getMixedRealm();
final rv = persistIfNecessary(
Expand Down

0 comments on commit 9e2285b

Please sign in to comment.