diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b72c66e..2d692c83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,37 @@ * Updated to Realm Sync 3.0.0-beta.4. * Tested against Realm Object Server 3.0.0-alpha.2. + +2.2.10 Release notes (2018-2-20) +============================================================= +### Breaking changes +* None. + +### Enhancements +* None. + +### Bug fixes +* [Object Server] A use-after-free bug was fixed which could cause arrays of primitives to behave unexpectedly. + +### Internal +* Updated to Realm Sync 2.2.12. + + +2.2.9 Release notes (2018-2-19) +============================================================= +### Breaking changes +* None. + +### Enhancements +* None. + +### Bug fixes +* Improved root certificate checking. + +### Internal +* Updated to Realm Sync 2.2.11. + + 2.2.8 Release notes (2018-2-13) ============================================================= ### Breaking changes @@ -50,7 +81,6 @@ ### Internal * None. ->>>>>>> 1ad557b47fa03b4085b8fb5c682598a36d79b966 2.2.6 Release notes (2018-1-26) ============================================================= diff --git a/lib/index.d.ts b/lib/index.d.ts index 878d8e82..9e59bd73 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -545,9 +545,9 @@ declare class Realm { /** * @param {string|Realm.ObjectSchema|Function} type * @param {number|string} key - * @returns T + * @returns {T | undefined} */ - objectForPrimaryKey(type: string | Realm.ObjectSchema | Function, key: number | string): T | null; + objectForPrimaryKey(type: string | Realm.ObjectSchema | Function, key: number | string): T | undefined; /** * @param {string|Realm.ObjectType|Function} type diff --git a/tests/js/index.js b/tests/js/index.js index 7aab4946..f7f52436 100644 --- a/tests/js/index.js +++ b/tests/js/index.js @@ -44,7 +44,7 @@ var TESTS = { MigrationTests: require('./migration-tests'), EncryptionTests: require('./encryption-tests'), ObjectIDTests: require('./object-id-tests'), - // GarbageCollectionTests: require('./garbage-collection'), + // Garbagecollectiontests: require('./garbage-collection'), }; // If sync is enabled, run the sync tests diff --git a/tests/js/list-tests.js b/tests/js/list-tests.js index 417cd5b6..72349803 100644 --- a/tests/js/list-tests.js +++ b/tests/js/list-tests.js @@ -37,7 +37,7 @@ module.exports = { TestCase.assertInstanceOf(obj.list, Realm.List); TestCase.assertInstanceOf(obj.list, Realm.Collection); }); - + TestCase.assertThrowsContaining(() => new Realm.List(), 'constructor'); TestCase.assertInstanceOf(Realm.List, Function); }, @@ -1223,4 +1223,83 @@ module.exports = { TestCase.assertThrowsContaining(() => object.list.avg(), "JS value must be of type 'string', got (undefined)"); }, + + testListNested: function() { + const realm = new Realm({schema: [schemas.ParentObject, schemas.NameObject]}); + realm.write(() => { + realm.create('ParentObject', { + id: 1, + name: [ + { family: 'Larsen', given: ['Hans', 'Jørgen'], prefix: [] }, + { family: 'Hansen', given: ['Ib'], prefix: [] } + ] + }); + realm.create('ParentObject', { + id: 2, + name: [ + {family: 'Petersen', given: ['Gurli', 'Margrete'], prefix: [] } + ] + }); + }); + + let objects = realm.objects('ParentObject'); + TestCase.assertEqual(objects.length, 2); + TestCase.assertEqual(objects[0].name.length, 2); + TestCase.assertEqual(objects[0].name[0].given.length, 2); + TestCase.assertEqual(objects[0].name[0].prefix.length, 0); + TestCase.assertEqual(objects[0].name[0].given[0], 'Hans'); + TestCase.assertEqual(objects[0].name[0].given[1], 'Jørgen') + TestCase.assertEqual(objects[0].name[1].given.length, 1); + TestCase.assertEqual(objects[0].name[1].given[0], 'Ib'); + TestCase.assertEqual(objects[0].name[1].prefix.length, 0); + + TestCase.assertEqual(objects[1].name.length, 1); + TestCase.assertEqual(objects[1].name[0].given.length, 2); + TestCase.assertEqual(objects[1].name[0].prefix.length, 0); + TestCase.assertEqual(objects[1].name[0].given[0], 'Gurli'); + TestCase.assertEqual(objects[1].name[0].given[1], 'Margrete'); + }, + + testListNestedFromJSON: function() { + let json = '{"id":1, "name": [{ "family": "Larsen", "given": ["Hans", "Jørgen"], "prefix": [] }, { "family": "Hansen", "given": ["Ib"], "prefix": [] }] }'; + let parent = JSON.parse(json); + const realm = new Realm({schema: [schemas.ParentObject, schemas.NameObject]}); + realm.write(() => { + realm.create('ParentObject', parent); + }); + + let objects = realm.objects('ParentObject'); + TestCase.assertEqual(objects.length, 1); + TestCase.assertEqual(objects[0].name.length, 2); + TestCase.assertEqual(objects[0].name[0].given.length, 2); + TestCase.assertEqual(objects[0].name[0].prefix.length, 0); + TestCase.assertEqual(objects[0].name[0].given[0], 'Hans'); + TestCase.assertEqual(objects[0].name[0].given[1], 'Jørgen'); + + TestCase.assertEqual(objects[0].name[1].given.length, 1); + TestCase.assertEqual(objects[0].name[1].prefix.length, 0); + TestCase.assertEqual(objects[0].name[1].given[0], 'Ib'); + }, + + testMultipleLists: function() { + const realm = new Realm({schema: [schemas.MultiListObject]}); + realm.write(() => { + realm.create('MultiListObject', { id: 0, list1: ["Hello"], list2: ["World"] }); + realm.create('MultiListObject', { id: 1, list1: ["Foo"], list2: ["Bar"] }); + }); + + let objects = realm.objects('MultiListObject'); + TestCase.assertEqual(objects.length, 2); + TestCase.assertEqual(objects[0].id, 0); + TestCase.assertEqual(objects[0].list1.length, 1); + TestCase.assertEqual(objects[0].list1[0], "Hello"); + TestCase.assertEqual(objects[0].list2.length, 1); + TestCase.assertEqual(objects[0].list2[0], "World"); + + TestCase.assertEqual(objects[1].id, 1); + TestCase.assertEqual(objects[1].list1.length, 1); + TestCase.assertEqual(objects[1].list1[0], "Foo"); + TestCase.assertEqual(objects[1].list2.length, 1); + TestCase.assertEqual(objects[1].list2[0], "Bar"); + } }; diff --git a/tests/js/nested-list-helper.js b/tests/js/nested-list-helper.js new file mode 100644 index 00000000..e4b0803c --- /dev/null +++ b/tests/js/nested-list-helper.js @@ -0,0 +1,67 @@ +/* +This script creates new nested objects into a new Realm. +*/ + +'use strict'; +console.log("nested-list-helper started"); +const username = process.argv[3]; +const realmName = process.argv[4]; +const realmModule = process.argv[5]; + +const Realm = require(realmModule); +let schemas = require(process.argv[2]); + +function createObjects(user) { + const config = { + sync: { user, + url: `realm://localhost:9080/~/${realmName}`, + error: err => console.log(err) + }, + schema: [schemas.ParentObject, schemas.NameObject], + }; + + const realm = new Realm(config); + + realm.write(() => { + realm.create('ParentObject', { + id: 1, + name: [ + { family: 'Larsen', given: ['Hans', 'Jørgen'], prefix: [] }, + { family: 'Hansen', given: ['Ib'], prefix: [] } + ] + }); + realm.create('ParentObject', { + id: 2, + name: [ + {family: 'Petersen', given: ['Gurli', 'Margrete'], prefix: [] } + ] + }); + }); + + console.log("JSON: " + JSON.stringify(realm.objects('ParentObject'))); + + let session = realm.syncSession; + return new Promise((resolve, reject) => { + let callback = (transferred, total) => { + if (transferred === total) { + session.removeProgressNotification(callback); + resolve(realm); + } + } + session.addProgressNotification('upload', 'forCurrentlyOutstandingWork', callback); + }); +} + +let registrationError; +Realm.Sync.User.register('http://localhost:9080', username, 'password') + .catch((error) => { + registrationError = JSON.stringify(error); + return Realm.Sync.User.login('http://localhost:9080', username, 'password') + }) + .catch((error) => { + const loginError = JSON.stringify(error); + console.error(`nested-list-helper failed:\n User.register() error:\n${registrationError}\n User.login() error:\n${registrationError}`); + process.exit(-2); + }) + .then((user) => createObjects(user)) + .then(() => process.exit(0)); diff --git a/tests/js/schemas.js b/tests/js/schemas.js index 6d9ecc75..8c153603 100644 --- a/tests/js/schemas.js +++ b/tests/js/schemas.js @@ -280,4 +280,30 @@ exports.LinkingObjectsObject = { links: 'LinkingObjectsObject[]', linkingObjects: {type: 'linkingObjects', objectType: 'LinkingObjectsObject', property: 'links'} } -} +}; + +exports.ParentObject = { + name: 'ParentObject', + properties: { + id: 'int', + name: 'NameObject[]' + } +}; + +exports.NameObject = { + name: 'NameObject', + properties: { + family: 'string', + given: 'string[]', + prefix: 'string[]' + } +}; + +exports.MultiListObject = { + name: 'MultiListObject', + properties: { + 'id': 'int', + 'list1': 'string[]', + 'list2': 'string[]' + } +}; diff --git a/tests/js/session-tests.js b/tests/js/session-tests.js index 90fc45ed..4af07aab 100644 --- a/tests/js/session-tests.js +++ b/tests/js/session-tests.js @@ -24,6 +24,7 @@ const Realm = require('realm'); const TestCase = require('./asserts'); +let schemas = require('./schemas'); const isNodeProccess = (typeof process === 'object' && process + '' === '[object process]'); @@ -402,6 +403,49 @@ module.exports = { }); }, + testListNestedSync() { + if (!isNodeProccess) { + return; + } + + const username = uuid(); + const realmName = uuid(); + + return runOutOfProcess(__dirname + '/nested-list-helper.js', __dirname + '/schemas.js', username, realmName, REALM_MODULE_PATH) + .then(() => { + return Realm.Sync.User.login('http://localhost:9080', username, 'password').then(user => { + return new Promise((resolve, reject) => { + let config = { + schema: [schemas.ParentObject, schemas.NameObject], + sync: { user, url: `realm://localhost:9080/~/${realmName}` } + }; + Realm.open(config).then(realm => { + let objects = realm.objects('ParentObject'); + + let json = JSON.stringify(objects); + TestCase.assertEqual(json, '{"0":{"id":1,"name":{"0":{"family":"Larsen","given":{"0":"Hans","1":"Jørgen"},"prefix":{}},"1":{"family":"Hansen","given":{"0":"Ib"},"prefix":{}}}},"1":{"id":2,"name":{"0":{"family":"Petersen","given":{"0":"Gurli","1":"Margrete"},"prefix":{}}}}}'); + TestCase.assertEqual(objects.length, 2); + TestCase.assertEqual(objects[0].name.length, 2); + TestCase.assertEqual(objects[0].name[0].given.length, 2); + TestCase.assertEqual(objects[0].name[0].prefix.length, 0); + TestCase.assertEqual(objects[0].name[0].given[0], 'Hans'); + TestCase.assertEqual(objects[0].name[0].given[1], 'Jørgen') + TestCase.assertEqual(objects[0].name[1].given.length, 1); + TestCase.assertEqual(objects[0].name[1].given[0], 'Ib'); + TestCase.assertEqual(objects[0].name[1].prefix.length, 0); + + TestCase.assertEqual(objects[1].name.length, 1); + TestCase.assertEqual(objects[1].name[0].given.length, 2); + TestCase.assertEqual(objects[1].name[0].prefix.length, 0); + TestCase.assertEqual(objects[1].name[0].given[0], 'Gurli'); + TestCase.assertEqual(objects[1].name[0].given[1], 'Margrete'); + resolve(); + }).catch(() => reject()); + }); + }); + }); + }, + testIncompatibleSyncedRealmOpen() { let realm = "sync-v1.realm"; if (isNodeProccess) {