diff --git a/CHANGELOG.md b/CHANGELOG.md index 040efa8ace..dc32f87f85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,9 +24,9 @@ NOTE 1: Requires MacOS v10.14 (Mojave) to build. * File format: generates Realms with format v10 (reads and upgrades file format v5 or later). ### Internal -* Updated Realm Core from ??? to Realm Core v10.0.0-alpha.2. -* Updated Realm Sync from ??? to Realm Sync v10.0.0-alpha.4. -* Updated Realm Object Store to commit 45b857fb94797258fb8fa5a3c4b13472a6095503. +* Updated Realm Core from ??? to Realm Core v10.0.0-alpha.4. +* Updated Realm Sync from ??? to Realm Sync v10.0.0-alpha.5. +* Updated Realm Object Store to commit 1577211c1959b60b10a967579dd2aaef2f571149. x.x.x Release notes (yyyy-MM-dd) diff --git a/dependencies.list b/dependencies.list index 6173d2febb..f7db2720e9 100644 --- a/dependencies.list +++ b/dependencies.list @@ -1,5 +1,5 @@ PACKAGE_NAME=realm-js VERSION=10.0.0-prealpha.0 -REALM_CORE_VERSION=10.0.0-alpha.3 -REALM_SYNC_VERSION=10.0.0-alpha.5 +REALM_CORE_VERSION=10.0.0-alpha.4 +REALM_SYNC_VERSION=10.0.0-alpha.6 REALM_OBJECT_SERVER_VERSION=3.23.1 diff --git a/src/js_object_accessor.hpp b/src/js_object_accessor.hpp index bdbd02814d..f961b797f8 100644 --- a/src/js_object_accessor.hpp +++ b/src/js_object_accessor.hpp @@ -62,6 +62,14 @@ class NativeAccessor { , m_object_schema(collection.get_type() == realm::PropertyType::Object ? &collection.get_object_schema() : nullptr) { } + NativeAccessor(NativeAccessor& na, Obj parent, Property const& prop) + : m_ctx(na.m_ctx) + , m_realm(na.m_realm) + , m_parent(std::move(parent)) + , m_property(&prop) + , m_object_schema(prop.type == realm::PropertyType::Object ? &*m_realm->schema().find(prop.object_type) : na.m_object_schema) + { } + NativeAccessor(NativeAccessor& parent, const Property& prop) : m_ctx(parent.m_ctx) , m_realm(parent.m_realm) @@ -73,10 +81,6 @@ class NativeAccessor { } } - bool is_embedded() const { - return m_object_schema ? bool(m_object_schema->is_embedded) : false; - } - OptionalValue value_for_property(ValueType dict, Property const& prop, size_t) { ObjectType object = Value::validated_to_object(m_ctx, dict); ValueType value = Object::get_property(m_ctx, object, !prop.public_name.empty() ? prop.public_name : prop.name); @@ -98,11 +102,10 @@ class NativeAccessor { template T unbox(ValueType value, realm::CreatePolicy policy = realm::CreatePolicy::Skip, ObjKey current_obj = ObjKey()); - Obj unbox_embedded(ValueType value, CreatePolicy policy, Obj& parent, ColKey col, size_t ndx) { - return realm::Object::create_embedded(*this, m_realm, *m_object_schema, value, policy, parent, col, ndx).obj(); + Obj create_embedded_object() { + return m_parent.create_and_set_linked_object(m_property->column_key); } - template util::Optional unbox_optional(ValueType value) { return is_null(value) ? util::none : util::make_optional(unbox(value)); @@ -178,6 +181,8 @@ class NativeAccessor { private: ContextType m_ctx; std::shared_ptr m_realm; + Obj m_parent; + const Property* m_property = nullptr; const ObjectSchema* m_object_schema; std::string m_string_buffer; OwnedBinaryData m_owned_binary_data; @@ -349,13 +354,10 @@ struct Unbox { if (realm_object->realm() == ctx->m_realm) { return realm_object->obj(); } - if (policy == realm::CreatePolicy::Skip) { + if (!policy.create) { throw std::runtime_error("Realm object is from another Realm"); } } - if (policy == realm::CreatePolicy::Skip) { - throw NonRealmObjectException(); - } if (Value::is_array(ctx->m_ctx, object)) { object = Schema::dict_for_property_array(ctx->m_ctx, *ctx->m_object_schema, object); diff --git a/src/object-store b/src/object-store index f18b240b8b..1577211c19 160000 --- a/src/object-store +++ b/src/object-store @@ -1 +1 @@ -Subproject commit f18b240b8bf592e5d5ae8045c5444f423b6d8e9d +Subproject commit 1577211c1959b60b10a967579dd2aaef2f571149 diff --git a/tests/js/list-tests.js b/tests/js/list-tests.js index e9022b3a4a..113281d19e 100644 --- a/tests/js/list-tests.js +++ b/tests/js/list-tests.js @@ -1412,13 +1412,72 @@ module.exports = { testCreateEmbeddedObjects: function() { const realm = new Realm({schema: [schemas.ContactSchema, schemas.AddressSchema]}); + realm.write(() => { // FIXME: This should not be required! + realm.deleteAll(); + }); + realm.write(() => { - realm.create(schemas.ContactSchema.name, { name: 'Freddy Krueger', address: { street: 'Elm Street', city: 'Springwood' }} ); + realm.create(schemas.ContactSchema.name, { name: "Freddy Krueger", address: { street: "Elm Street", city: "Springwood" }} ); }); TestCase.assertEqual(realm.objects(schemas.ContactSchema.name).length, 1); TestCase.assertEqual(realm.objects(schemas.AddressSchema.name).length, 1); + realm.write(() => { + realm.create(schemas.ContactSchema.name, { name: "John Doe" } ); + }); + + let contacts = realm.objects(schemas.ContactSchema.name); + TestCase.assertEqual(contacts.length, 2); + TestCase.assertEqual(realm.objects(schemas.AddressSchema.name).length, 1); + TestCase.assertEqual(contacts[0]["address"]["street"], "Elm Street"); + TestCase.assertNull(contacts[1]["address"]); + + realm.close(); + }, + + + testCreateMultipleEmbeddedObjects: function() { + const realm = new Realm({schema: [schemas.HouseOwnerSchema, schemas.AddressSchema]}); + realm.write(() => { // FIXME: This should not be required! + realm.deleteAll(); + }); + + realm.write(() => { + realm.create(schemas.HouseOwnerSchema.name, { name: "Ib", addresses: [ + { street: "Algade", city: "Nordby" }, + { street: "Skolevej", city: "Sydpynten" } + ]}); + realm.create(schemas.HouseOwnerSchema.name, { name: "Petra", addresses: [ + { street: "Algade", city: "Nordby" } + ]}); + realm.create(schemas.HouseOwnerSchema.name, { name: "Hans" }); + }); + + let owners = realm.objects(schemas.HouseOwnerSchema.name).sorted("name"); + let addresses = realm.objects(schemas.AddressSchema.name).sorted("street"); + TestCase.assertEqual(owners.length, 3); + TestCase.assertEqual(addresses.length, 3); + + const names = ["Hans", "Ib", "Petra"]; + for (let i = 0; i < names.length; i++) { + TestCase.assertEqual(owners[i]["name"], names[i]); + } + + let streets = ["Algade", "Algade", "Skolevej"]; + for (let i = 0; i < streets.length; i++) { + TestCase.assertEqual(addresses[i]["street"], streets[i]); + } + + realm.write(() => { + addresses[0]["street"] = "Strandvejen"; + }); + + streets = ["Algade", "Skolevej", "Strandvejen"]; + for (let i = 0; i < streets.length; i++) { + TestCase.assertEqual(addresses[i]["street"], streets[i]); + } + realm.close(); } }; diff --git a/tests/js/query-tests.js b/tests/js/query-tests.js index 421baa84af..775feac7a9 100644 --- a/tests/js/query-tests.js +++ b/tests/js/query-tests.js @@ -238,6 +238,10 @@ module.exports = { testQueryDecimal: function() { var realm = new Realm({ schema: [schemas.DecimalObject] }); + realm.write(() => { // FIXME: This should not be required! + realm.deleteAll(); + }); + realm.write(function () { [0, 1, 2].forEach(v => { realm.create(schemas.DecimalObject.name, { decimalCol: Decimal128.fromString(`1000${v}`) }); diff --git a/tests/js/realm-tests.js b/tests/js/realm-tests.js index 3084f2bdf2..be61b86502 100644 --- a/tests/js/realm-tests.js +++ b/tests/js/realm-tests.js @@ -1673,37 +1673,112 @@ module.exports = { testDecimal128: function() { const realm = new Realm({schema: [schemas.DecimalObject]}); + realm.write(() => { // FIXME: This should not be required! + realm.deleteAll(); + }); - let d = Decimal128.fromString("42"); - realm.write(() => { - realm.create(schemas.DecimalObject.name, { decimalCol: d}); + let numbers = [42, 3.1415, 6.022e23, -7, -100.2, 1.02E9]; + + numbers.forEach(number => { + let d = Decimal128.fromString(number.toString()); + realm.write(() => { + realm.create(schemas.DecimalObject.name, { decimalCol: d}); + }); }); let objects = realm.objects(schemas.DecimalObject.name); - TestCase.assertEqual(objects.length, 1); + TestCase.assertEqual(objects.length, numbers.length); + + for (let i = 0; i < numbers.length; i++) { + let d128 = objects[i]['decimalCol']; + TestCase.assertTrue(d128 instanceof Decimal128); + TestCase.assertEqual(d128.toString(), numbers[i].toString().toUpperCase()); + } + + realm.close(); + }, + + testDecimal128_LargeNumbers: function() { + const realm = new Realm({schema: [schemas.DecimalObject]}); + realm.write(() => { // FIXME: This should not be required! + realm.deleteAll(); + }); + let numbers = ["1.02e6102", "-1.02e6102", "1.02e-6102", "9.99e6143", "1e-6142"]; + + numbers.forEach(number => { + let d = Decimal128.fromString(number); + realm.write(() => { + realm.create(schemas.DecimalObject.name, { decimalCol: d}); + }); + }); + + let objects = realm.objects(schemas.DecimalObject.name); + TestCase.assertEqual(objects.length, numbers.length); - let d128 = objects[0]['decimalCol']; - TestCase.assertTrue(d128 instanceof Decimal128); - TestCase.assertEqual(d128.toString(), "42"); + for (let i = 0; i < numbers.length; i++) { + let d128 = objects[i]['decimalCol']; + TestCase.assertTrue(d128 instanceof Decimal128); + TestCase.assertEqual(d128.toString(), numbers[i].toUpperCase()); + } realm.close(); }, testObjectId: function() { const realm = new Realm({schema: [schemas.ObjectIdObject]}); + realm.write(() => { // FIXME: This should not be required! + realm.deleteAll(); + }); + let values = ["0000002a9a7969d24bea4cf2", "0000002a9a7969d24bea4cf3"]; + let oids = []; - let oid1 = new ObjectId('0000002a9a7969d24bea4cf2'); - realm.write(() => { - realm.create(schemas.ObjectIdObject.name, { id: oid1 }); + values.forEach(v => { + let oid = new ObjectId(); + realm.write(() => { + realm.create(schemas.ObjectIdObject.name, { id: oid }); + }); + oids.push(oid); }); let objects = realm.objects(schemas.ObjectIdObject.name); - TestCase.assertEqual(objects.length, 1); + TestCase.assertEqual(objects.length, values.length); + + for (let i = 0; i < values.length; i++) { + let oid2 = objects[i]['id']; + TestCase.assertTrue(oid2 instanceof ObjectId, 'instaceof'); + TestCase.assertTrue(oids[i].equals(oid2), 'equal'); + TestCase.assertEqual(oid2.toHexString(), oids[i].toHexString()); + } + + realm.close(); + }, + + testObjectIdFromTimestamp: function() { + const realm = new Realm({schema: [schemas.ObjectIdObject]}); + realm.write(() => { // FIXME: This should not be required! + realm.deleteAll(); + }); + let values = [1, 1000000000, 2000000000]; + let oids = []; - let oid2 = objects[0]['id']; - TestCase.assertTrue(oid2 instanceof ObjectId, 'instaceof'); - TestCase.assertTrue(oid1.equals(oid2), 'equal'); - TestCase.assertEqual(oid2.toHexString(), oid1.toHexString()); + values.forEach(v => { + let oid = ObjectId.createFromTime(v); + realm.write(() => { + realm.create(schemas.ObjectIdObject.name, { id: oid }); + }); + oids.push(oid); + }); + + let objects = realm.objects(schemas.ObjectIdObject.name); + TestCase.assertEqual(objects.length, values.length); + + for (let i = 0; i < values.length; i++) { + let oid2 = objects[i]['id']; + TestCase.assertTrue(oid2 instanceof ObjectId, 'instaceof'); + TestCase.assertTrue(oids[i].equals(oid2), 'equal'); + TestCase.assertEqual(oid2.toHexString(), oids[i].toHexString()); + TestCase.assertEqual(oid2.getTimestamp().toISOString(), oids[i].getTimestamp().toISOString()); + } realm.close(); }, diff --git a/tests/js/results-tests.js b/tests/js/results-tests.js index 5fe27e1f2a..070fa05cd8 100644 --- a/tests/js/results-tests.js +++ b/tests/js/results-tests.js @@ -263,6 +263,10 @@ module.exports = { testResultsSortedAllTypes: function() { var realm = new Realm({schema: [schemas.BasicTypes]}); + realm.write(() => { // FIXME: This should not be required! + realm.deleteAll(); + }); + var objects = realm.objects('BasicTypesObject'); var decimals = []; @@ -274,8 +278,8 @@ module.exports = { realm.write(function() { realm.create('BasicTypesObject', [false, 0, 0, 0, '0', new Date(0), new ArrayBuffer(), decimals[0], oids[0]]); - realm.create('BasicTypesObject', [true, 2, 2, 2, '2', new Date(2), new ArrayBuffer(), decimals[1], oids[1]]); - realm.create('BasicTypesObject', [false, 1, 1, 1, '1', new Date(1), new ArrayBuffer(), decimals[2], oids[2]]); + realm.create('BasicTypesObject', [true, 2, 2, 2, '2', new Date(2), new ArrayBuffer(), decimals[2], oids[2]]); + realm.create('BasicTypesObject', [false, 1, 1, 1, '1', new Date(1), new ArrayBuffer(), decimals[1], oids[1]]); }); var numberProps = ['intCol', 'floatCol', 'doubleCol', 'stringCol']; @@ -309,12 +313,12 @@ module.exports = { TestCase.assertEqual(objects[1].boolCol, false, 'second element descending for boolCol'); TestCase.assertEqual(objects[2].boolCol, false, 'third element descending for boolCol'); - objects = objects.sorted('decimalCol', true); + objects = objects.sorted('decimalCol', false); for (var i = 0; i < 3; i++) { TestCase.assertEqual(objects[i].decimalCol.toString(), decimals[i].toString(), `element ${i} ascending for decimal`); } - objects = objects.sorted('decimalCol', false); + objects = objects.sorted('decimalCol', true); for (var i = 0; i < 3; i++) { TestCase.assertEqual(objects[i].decimalCol.toString(), decimals[2-i].toString(), `element ${i} descending for decimal`); } diff --git a/tests/js/schemas.js b/tests/js/schemas.js index 94b6f35f16..f14f2d5cbf 100644 --- a/tests/js/schemas.js +++ b/tests/js/schemas.js @@ -423,6 +423,14 @@ exports.ContactSchema = { } }; +exports.HouseOwnerSchema = { + name: 'HouseOwner', + properties: { + name: 'string', + addresses: { type: "list", objectType: "Address" } + } +}; + exports.AddressSchema = { name: 'Address', embedded: true, @@ -430,4 +438,4 @@ exports.AddressSchema = { street: 'string', city: 'string' } -}; \ No newline at end of file +};