From b76ed200209d1f25af1a2c5a1047a6e3f3716bb8 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Fri, 27 May 2016 11:30:17 -0700 Subject: [PATCH 01/21] Update projects to React Native 0.26.2 Fixed some minor issues along the way. --- examples/ReactExample/components/todo-app.js | 3 +-- examples/ReactExample/package.json | 4 ++-- examples/ReactExample/tests/util.js | 4 ++-- examples/ReactNativeBenchmarks/benchmarks.js | 3 +-- examples/ReactNativeBenchmarks/package.json | 4 ++-- tests/react-test-app/package.json | 4 ++-- 6 files changed, 10 insertions(+), 12 deletions(-) diff --git a/examples/ReactExample/components/todo-app.js b/examples/ReactExample/components/todo-app.js index 31e0d55a..c0d03f70 100644 --- a/examples/ReactExample/components/todo-app.js +++ b/examples/ReactExample/components/todo-app.js @@ -21,7 +21,6 @@ import React from 'react'; import { - Component, Navigator, Platform, StatusBar, @@ -35,7 +34,7 @@ import TodoListView from './todo-listview'; import realm from './realm'; import styles from './styles'; -export default class TodoApp extends Component { +export default class TodoApp extends React.Component { constructor(props) { super(props); diff --git a/examples/ReactExample/package.json b/examples/ReactExample/package.json index ce59f399..22a0147e 100644 --- a/examples/ReactExample/package.json +++ b/examples/ReactExample/package.json @@ -6,8 +6,8 @@ "start": "react-native start" }, "dependencies": { - "react": "^0.14.8", - "react-native": "^0.25.1", + "react": "15.0.2", + "react-native": "^0.26.2", "realm": "file:../.." } } diff --git a/examples/ReactExample/tests/util.js b/examples/ReactExample/tests/util.js index 5ee41443..800118c5 100644 --- a/examples/ReactExample/tests/util.js +++ b/examples/ReactExample/tests/util.js @@ -18,11 +18,11 @@ 'use strict'; -import React from 'react-native'; +import React from 'react'; const rootComponentPromise = new Promise((resolve) => { // Require internal module here so the promise is rejected if there is an error. - let Mount = require('react-native/Libraries/ReactNative/ReactNativeMount'); + let Mount = require('react/lib/ReactNativeMount'); let renderComponent = Mount.renderComponent; Mount.renderComponent = function() { diff --git a/examples/ReactNativeBenchmarks/benchmarks.js b/examples/ReactNativeBenchmarks/benchmarks.js index ea8c2322..1e397793 100644 --- a/examples/ReactNativeBenchmarks/benchmarks.js +++ b/examples/ReactNativeBenchmarks/benchmarks.js @@ -21,7 +21,6 @@ import React from 'react'; import { - Component, StyleSheet, Text, View, @@ -355,7 +354,7 @@ class RNSqliteTests extends Tests { const apiTests = [new RealmTests, new RNSqliteTests, new RNStoreTests]; -export default class ReactNativeBenchmarks extends Component { +export default class ReactNativeBenchmarks extends React.Component { constructor(props) { super(props); diff --git a/examples/ReactNativeBenchmarks/package.json b/examples/ReactNativeBenchmarks/package.json index 823ee573..35b67f07 100644 --- a/examples/ReactNativeBenchmarks/package.json +++ b/examples/ReactNativeBenchmarks/package.json @@ -6,8 +6,8 @@ "start": "react-native start" }, "dependencies": { - "react": "^0.14.8", - "react-native": "^0.25.1", + "react": "15.0.2", + "react-native": "^0.26.2", "react-native-sqlite-storage": "^2.1.3", "react-native-store": "^0.4.1", "realm": "file:../.." diff --git a/tests/react-test-app/package.json b/tests/react-test-app/package.json index be90074d..6e9f6953 100644 --- a/tests/react-test-app/package.json +++ b/tests/react-test-app/package.json @@ -6,8 +6,8 @@ "start": "react-native start" }, "dependencies": { - "react": "^0.14.8", - "react-native": "^0.25.1", + "react": "15.0.2", + "react-native": "^0.26.2", "react-native-fs": "^1.1.0", "xmlbuilder": "^4.2.1", "realm": "file:../..", From 3b9b8cbc75d996d00124017418b1b29b462bfda8 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Tue, 31 May 2016 11:30:24 -0700 Subject: [PATCH 02/21] Remove unused GCov_Build configuration We've never really used this, so let's remove it until we ever actually need something like this. --- src/RealmJS.xcodeproj/project.pbxproj | 134 -------------------------- 1 file changed, 134 deletions(-) diff --git a/src/RealmJS.xcodeproj/project.pbxproj b/src/RealmJS.xcodeproj/project.pbxproj index 2e662b1b..bafed5b7 100644 --- a/src/RealmJS.xcodeproj/project.pbxproj +++ b/src/RealmJS.xcodeproj/project.pbxproj @@ -976,87 +976,6 @@ }; name = Release; }; - 02F9EE1C1B6BF66300C807E8 /* GCov_Build */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "c++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0.13.2; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_GENERATE_TEST_COVERAGE_FILES = YES; - GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - REALM_HAVE_CONFIG, - __ASSERTMACROS__, - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - "$(SRCROOT)/object-store/external/pegtl", - "$(SRCROOT)/object-store/src", - "$(SRCROOT)/../vendor", - ); - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LIBRARY_SEARCH_PATHS = ../core; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - OTHER_CPLUSPLUSFLAGS = ( - "$(OTHER_CFLAGS)", - "-isystem", - ../core/include, - "-ftemplate-backtrace-limit=0", - ); - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = GCov_Build; - }; - 02F9EE1E1B6BF66300C807E8 /* GCov_Build */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - INFOPLIST_FILE = ../tests/ios/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - OTHER_CPLUSPLUSFLAGS = ( - "$(OTHER_CFLAGS)", - "-isystem", - core/include, - ); - PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = GCov_Build; - }; F62BF8FC1CAC71780022BCDC /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1088,35 +1007,6 @@ }; name = Debug; }; - F62BF8FD1CAC71780022BCDC /* GCov_Build */ = { - isa = XCBuildConfiguration; - buildSettings = { - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 0.13.2; - EXECUTABLE_PREFIX = lib; - GCC_PREPROCESSOR_DEFINITIONS = ( - "REALM_PLATFORM_NODE=1", - "$(inherited)", - ); - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(SRCROOT)/../node_modules/nan", - /usr/local/include/node, - ); - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - /usr/local/lib, - ); - OTHER_LDFLAGS = ( - "-lrealm", - "-luv", - "-lv8", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx; - }; - name = GCov_Build; - }; F62BF8FE1CAC71780022BCDC /* Release */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1160,15 +1050,6 @@ }; name = Debug; }; - F63FF2B81C1241E500B3B8E0 /* GCov_Build */ = { - isa = XCBuildConfiguration; - buildSettings = { - OTHER_LIBTOOLFLAGS = "$(SRCROOT)/../core/librealm-ios-bitcode.a"; - PRODUCT_NAME = RealmJS; - SKIP_INSTALL = YES; - }; - name = GCov_Build; - }; F63FF2B91C1241E500B3B8E0 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1193,16 +1074,6 @@ }; name = Debug; }; - F63FF2F71C16405D00B3B8E0 /* GCov_Build */ = { - isa = XCBuildConfiguration; - buildSettings = { - HEADER_SEARCH_PATHS = ""; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - }; - name = GCov_Build; - }; F63FF2F81C16405D00B3B8E0 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1220,7 +1091,6 @@ isa = XCConfigurationList; buildConfigurations = ( 02B58CC51AE99CEC009B348C /* Debug */, - 02F9EE1C1B6BF66300C807E8 /* GCov_Build */, 02B58CC61AE99CEC009B348C /* Release */, ); defaultConfigurationIsVisible = 0; @@ -1230,7 +1100,6 @@ isa = XCConfigurationList; buildConfigurations = ( 02B58CCB1AE99CEC009B348C /* Debug */, - 02F9EE1E1B6BF66300C807E8 /* GCov_Build */, 02B58CCC1AE99CEC009B348C /* Release */, ); defaultConfigurationIsVisible = 0; @@ -1240,7 +1109,6 @@ isa = XCConfigurationList; buildConfigurations = ( F62BF8FC1CAC71780022BCDC /* Debug */, - F62BF8FD1CAC71780022BCDC /* GCov_Build */, F62BF8FE1CAC71780022BCDC /* Release */, ); defaultConfigurationIsVisible = 0; @@ -1250,7 +1118,6 @@ isa = XCConfigurationList; buildConfigurations = ( F63FF2B71C1241E500B3B8E0 /* Debug */, - F63FF2B81C1241E500B3B8E0 /* GCov_Build */, F63FF2B91C1241E500B3B8E0 /* Release */, ); defaultConfigurationIsVisible = 0; @@ -1260,7 +1127,6 @@ isa = XCConfigurationList; buildConfigurations = ( F63FF2F61C16405D00B3B8E0 /* Debug */, - F63FF2F71C16405D00B3B8E0 /* GCov_Build */, F63FF2F81C16405D00B3B8E0 /* Release */, ); defaultConfigurationIsVisible = 0; From efdf0e01a9700f5536999eef32d01e02fbf72c14 Mon Sep 17 00:00:00 2001 From: Mark Rowe Date: Tue, 31 May 2016 15:27:48 -0700 Subject: [PATCH 03/21] Avoid copying `List` unnecessarily. --- src/js_list.hpp | 6 +++--- src/js_object_accessor.hpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/js_list.hpp b/src/js_list.hpp index d936159c..52fe358c 100644 --- a/src/js_list.hpp +++ b/src/js_list.hpp @@ -41,7 +41,7 @@ struct ListClass : ClassDefinition> { using Value = js::Value; using ReturnValue = js::ReturnValue; - static ObjectType create_instance(ContextType, realm::List &); + static ObjectType create_instance(ContextType, realm::List); // properties static void get_length(ContextType, ObjectType, ReturnValue &); @@ -81,8 +81,8 @@ struct ListClass : ClassDefinition> { }; template -typename T::Object ListClass::create_instance(ContextType ctx, realm::List &list) { - return create_object>(ctx, new realm::List(list)); +typename T::Object ListClass::create_instance(ContextType ctx, realm::List list) { + return create_object>(ctx, new realm::List(std::move(list))); } template diff --git a/src/js_object_accessor.hpp b/src/js_object_accessor.hpp index 4809f23a..dead643e 100644 --- a/src/js_object_accessor.hpp +++ b/src/js_object_accessor.hpp @@ -135,7 +135,7 @@ struct NativeAccessor { return Object::validated_get_object(ctx, Value::validated_to_object(ctx, value), (uint32_t)index); } static ValueType from_list(ContextType ctx, realm::List list) { - return ListClass::create_instance(ctx, list); + return ListClass::create_instance(ctx, std::move(list)); } static Mixed to_mixed(ContextType ctx, ValueType &val) { From 344fc42d4e326a0e2f27fda80637a76663ad259b Mon Sep 17 00:00:00 2001 From: Mark Rowe Date: Tue, 31 May 2016 15:54:43 -0700 Subject: [PATCH 04/21] Avoid copying `Object` unnecessarily. --- src/js_list.hpp | 8 ++++---- src/js_object_accessor.hpp | 2 +- src/js_realm.hpp | 2 +- src/js_realm_object.hpp | 6 +++--- src/js_results.hpp | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/js_list.hpp b/src/js_list.hpp index 52fe358c..ad119f5b 100644 --- a/src/js_list.hpp +++ b/src/js_list.hpp @@ -96,7 +96,7 @@ void ListClass::get_index(ContextType ctx, ObjectType object, uint32_t index, auto list = get_internal>(object); auto realm_object = realm::Object(list->get_realm(), list->get_object_schema(), list->get(index)); - return_value.set(RealmObjectClass::create_instance(ctx, realm_object)); + return_value.set(RealmObjectClass::create_instance(ctx, std::move(realm_object))); } template @@ -132,7 +132,7 @@ void ListClass::pop(ContextType ctx, ObjectType this_object, size_t argc, con size_t index = size - 1; auto realm_object = realm::Object(list->get_realm(), list->get_object_schema(), list->get(index)); - return_value.set(RealmObjectClass::create_instance(ctx, realm_object)); + return_value.set(RealmObjectClass::create_instance(ctx, std::move(realm_object))); list->remove(index); } } @@ -161,7 +161,7 @@ void ListClass::shift(ContextType ctx, ObjectType this_object, size_t argc, c else { auto realm_object = realm::Object(list->get_realm(), list->get_object_schema(), list->get(0)); - return_value.set(RealmObjectClass::create_instance(ctx, realm_object)); + return_value.set(RealmObjectClass::create_instance(ctx, std::move(realm_object))); list->remove(0); } } @@ -192,7 +192,7 @@ void ListClass::splice(ContextType ctx, ObjectType this_object, size_t argc, for (size_t i = 0; i < remove; i++) { auto realm_object = realm::Object(list->get_realm(), list->get_object_schema(), list->get(index)); - removed_objects.push_back(RealmObjectClass::create_instance(ctx, realm_object)); + removed_objects.push_back(RealmObjectClass::create_instance(ctx, std::move(realm_object))); list->remove(index); } for (size_t i = 2; i < argc; i++) { diff --git a/src/js_object_accessor.hpp b/src/js_object_accessor.hpp index dead643e..b6e8eb40 100644 --- a/src/js_object_accessor.hpp +++ b/src/js_object_accessor.hpp @@ -125,7 +125,7 @@ struct NativeAccessor { throw std::runtime_error("object is not a Realm Object"); } static ValueType from_object(ContextType ctx, realm::Object realm_object) { - return RealmObjectClass::create_instance(ctx, realm_object); + return RealmObjectClass::create_instance(ctx, std::move(realm_object)); } static size_t list_size(ContextType ctx, ValueType &value) { diff --git a/src/js_realm.hpp b/src/js_realm.hpp index a3241c1e..ae2d6b08 100644 --- a/src/js_realm.hpp +++ b/src/js_realm.hpp @@ -491,7 +491,7 @@ void RealmClass::create(ContextType ctx, ObjectType this_object, size_t argc, } auto realm_object = realm::Object::create(ctx, realm, *object_schema, object, update); - return_value.set(RealmObjectClass::create_instance(ctx, realm_object)); + return_value.set(RealmObjectClass::create_instance(ctx, std::move(realm_object))); } template diff --git a/src/js_realm_object.hpp b/src/js_realm_object.hpp index 846d3388..e2e72658 100644 --- a/src/js_realm_object.hpp +++ b/src/js_realm_object.hpp @@ -40,7 +40,7 @@ struct RealmObjectClass : ClassDefinition { using Function = js::Function; using ReturnValue = js::ReturnValue; - static ObjectType create_instance(ContextType, realm::Object &); + static ObjectType create_instance(ContextType, realm::Object); static void get_property(ContextType, ObjectType, const String &, ReturnValue &); static bool set_property(ContextType, ObjectType, const String &, ValueType); @@ -67,12 +67,12 @@ void RealmObjectClass::is_valid(ContextType ctx, ObjectType this_object, size } template -typename T::Object RealmObjectClass::create_instance(ContextType ctx, realm::Object &realm_object) { +typename T::Object RealmObjectClass::create_instance(ContextType ctx, realm::Object realm_object) { static String prototype_string = "prototype"; auto delegate = get_delegate(realm_object.realm().get()); auto name = realm_object.get_object_schema().name; - auto object = create_object>(ctx, new realm::Object(realm_object)); + auto object = create_object>(ctx, new realm::Object(std::move(realm_object))); if (!delegate || !delegate->m_constructors.count(name)) { return object; diff --git a/src/js_results.hpp b/src/js_results.hpp index 9f021fb7..640d67fb 100644 --- a/src/js_results.hpp +++ b/src/js_results.hpp @@ -208,7 +208,7 @@ void ResultsClass::get_index(ContextType ctx, ObjectType object, uint32_t ind } auto realm_object = realm::Object(results->get_realm(), results->get_object_schema(), results->get(index)); - return_value.set(RealmObjectClass::create_instance(ctx, realm_object)); + return_value.set(RealmObjectClass::create_instance(ctx, std::move(realm_object))); } template From d86e3b642ed1e83b7b70d2613f59a0e2ba38e148 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Tue, 31 May 2016 11:06:16 -0700 Subject: [PATCH 05/21] Add new files to Android.mk --- react-native/android/src/main/jni/Android.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/react-native/android/src/main/jni/Android.mk b/react-native/android/src/main/jni/Android.mk index ebc54405..abdf2352 100644 --- a/react-native/android/src/main/jni/Android.mk +++ b/react-native/android/src/main/jni/Android.mk @@ -37,7 +37,8 @@ LOCAL_SRC_FILES := \ src/object-store/src/impl/realm_coordinator.cpp \ src/object-store/src/impl/results_notifier.cpp \ src/object-store/src/impl/transact_log_handler.cpp \ - src/object-store/src/impl/generic/external_commit_helper.cpp \ + src/object-store/src/impl/android/external_commit_helper.cpp \ + src/object-store/src/impl/android/weak_realm_notifier.cpp \ vendor/base64.cpp LOCAL_C_INCLUDES := src From cd0bb079b750d62600b26bc318284abd3be1990e Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Fri, 3 Jun 2016 16:43:36 -0700 Subject: [PATCH 06/21] Implement objectForPrimaryKey() method Resolves #328 --- lib/browser/index.js | 9 ++++ src/js_realm.hpp | 58 ++++++++++++++++++------ src/js_results.hpp | 15 ++---- src/object-store/src/object_accessor.hpp | 51 +++++++++++++++++---- tests/js/realm-tests.js | 37 +++++++++++++++ tests/js/schemas.js | 9 ++++ 6 files changed, 145 insertions(+), 34 deletions(-) diff --git a/lib/browser/index.js b/lib/browser/index.js index f14f22ef..b189a7e4 100644 --- a/lib/browser/index.js +++ b/lib/browser/index.js @@ -106,6 +106,15 @@ export default class Realm { let method = util.createMethod(objectTypes.REALM, 'objects'); return method.apply(this, [type, ...args]); } + + objectForPrimaryKey(type, ...args) { + if (typeof type == 'function') { + type = objects.typeForConstructor(this[keys.realm], type); + } + + let method = util.createMethod(objectTypes.REALM, 'objectForPrimaryKey'); + return method.apply(this, [type, ...args]); + } } // Non-mutating methods: diff --git a/src/js_realm.hpp b/src/js_realm.hpp index ae2d6b08..271f7fa4 100644 --- a/src/js_realm.hpp +++ b/src/js_realm.hpp @@ -141,6 +141,7 @@ public: // methods static void objects(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &); + static void object_for_primary_key(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &); static void create(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &); static void delete_one(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &); static void delete_all(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &); @@ -180,6 +181,7 @@ public: MethodMap const methods = { {"objects", wrap}, + {"objectForPrimaryKey", wrap}, {"create", wrap}, {"delete", wrap}, {"deleteAll", wrap}, @@ -207,19 +209,35 @@ public: } // converts constructor object or type name to type name - static std::string validated_object_type_for_value(SharedRealm &realm, ContextType ctx, const ValueType &value) { + static const ObjectSchema& validated_object_schema_for_value(ContextType ctx, const SharedRealm &realm, const ValueType &value) { + std::string object_type; + if (Value::is_constructor(ctx, value)) { FunctionType constructor = Value::to_constructor(ctx, value); auto delegate = get_delegate(realm.get()); for (auto &pair : delegate->m_constructors) { if (FunctionType(pair.second) == constructor) { - return pair.first; + object_type = pair.first; + break; } } - throw std::runtime_error("Constructor was not registered in the schema for this Realm"); + + if (object_type.empty()) { + throw std::runtime_error("Constructor was not registered in the schema for this Realm"); + } } - return Value::validated_to_string(ctx, value, "objectType"); + else { + object_type = Value::validated_to_string(ctx, value, "objectType"); + } + + auto &schema = realm->config().schema; + auto object_schema = schema->find(object_type); + + if (object_schema == schema->end()) { + throw std::runtime_error("Object type '" + object_type + "' not found in schema."); + } + return *object_schema; } static std::string normalize_path(std::string path) { @@ -462,9 +480,25 @@ void RealmClass::objects(ContextType ctx, ObjectType this_object, size_t argc validate_argument_count(argc, 1); SharedRealm realm = *get_internal>(this_object); - std::string type = validated_object_type_for_value(realm, ctx, arguments[0]); + auto &object_schema = validated_object_schema_for_value(ctx, realm, arguments[0]); - return_value.set(ResultsClass::create_instance(ctx, realm, type)); + return_value.set(ResultsClass::create_instance(ctx, realm, object_schema)); +} + +template +void RealmClass::object_for_primary_key(ContextType ctx, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) { + validate_argument_count(argc, 2); + + SharedRealm realm = *get_internal>(this_object); + auto &object_schema = validated_object_schema_for_value(ctx, realm, arguments[0]); + auto realm_object = realm::Object::get_for_primary_key(ctx, realm, object_schema, arguments[1]); + + if (realm_object.is_valid()) { + return_value.set(RealmObjectClass::create_instance(ctx, std::move(realm_object))); + } + else { + return_value.set_undefined(); + } } template @@ -472,17 +506,11 @@ void RealmClass::create(ContextType ctx, ObjectType this_object, size_t argc, validate_argument_count(argc, 2, 3); SharedRealm realm = *get_internal>(this_object); - std::string className = validated_object_type_for_value(realm, ctx, arguments[0]); - auto &schema = realm->config().schema; - auto object_schema = schema->find(className); - - if (object_schema == schema->end()) { - throw std::runtime_error("Object type '" + className + "' not found in schema."); - } + auto &object_schema = validated_object_schema_for_value(ctx, realm, arguments[0]); ObjectType object = Value::validated_to_object(ctx, arguments[1], "properties"); if (Value::is_array(ctx, arguments[1])) { - object = Schema::dict_for_property_array(ctx, *object_schema, object); + object = Schema::dict_for_property_array(ctx, object_schema, object); } bool update = false; @@ -490,7 +518,7 @@ void RealmClass::create(ContextType ctx, ObjectType this_object, size_t argc, update = Value::validated_to_boolean(ctx, arguments[2], "update"); } - auto realm_object = realm::Object::create(ctx, realm, *object_schema, object, update); + auto realm_object = realm::Object::create(ctx, realm, object_schema, object, update); return_value.set(RealmObjectClass::create_instance(ctx, std::move(realm_object))); } diff --git a/src/js_results.hpp b/src/js_results.hpp index 640d67fb..5ef44699 100644 --- a/src/js_results.hpp +++ b/src/js_results.hpp @@ -40,7 +40,7 @@ struct ResultsClass : ClassDefinition> { static ObjectType create_instance(ContextType, const realm::Results &, bool live = true); static ObjectType create_instance(ContextType, const realm::List &, bool live = true); - static ObjectType create_instance(ContextType, SharedRealm, const std::string &type, bool live = true); + static ObjectType create_instance(ContextType, SharedRealm, const ObjectSchema &, bool live = true); static ObjectType create_instance(ContextType, SharedRealm, const ObjectSchema &, Query, bool live = true); template @@ -87,16 +87,9 @@ typename T::Object ResultsClass::create_instance(ContextType ctx, const realm } template -typename T::Object ResultsClass::create_instance(ContextType ctx, SharedRealm realm, const std::string &type, bool live) { - auto table = ObjectStore::table_for_object_type(realm->read_group(), type); - auto &schema = realm->config().schema; - auto object_schema = schema->find(type); - - if (object_schema == schema->end()) { - throw std::runtime_error("Object type '" + type + "' not present in Realm."); - } - - auto results = new realm::Results(realm, *object_schema, *table); +typename T::Object ResultsClass::create_instance(ContextType ctx, SharedRealm realm, const ObjectSchema &object_schema, bool live) { + auto table = ObjectStore::table_for_object_type(realm->read_group(), object_schema.name); + auto results = new realm::Results(realm, object_schema, *table); results->set_live(live); return create_object>(ctx, results); diff --git a/src/object-store/src/object_accessor.hpp b/src/object-store/src/object_accessor.hpp index c20282b6..f57f42e7 100644 --- a/src/object-store/src/object_accessor.hpp +++ b/src/object-store/src/object_accessor.hpp @@ -45,6 +45,9 @@ namespace realm { template static inline Object create(ContextType ctx, SharedRealm realm, const ObjectSchema &object_schema, ValueType value, bool try_update); + template + static Object get_for_primary_key(ContextType ctx, SharedRealm realm, const ObjectSchema &object_schema, ValueType primary_value); + SharedRealm realm() { return m_realm; } const ObjectSchema &get_object_schema() { return *m_object_schema; } Row row() { return m_row; } @@ -60,6 +63,9 @@ namespace realm { inline void set_property_value_impl(ContextType ctx, const Property &property, ValueType value, bool try_update); template inline ValueType get_property_value_impl(ContextType ctx, const Property &property); + + template + static size_t get_for_primary_key_impl(ContextType ctx, const ConstTableRef &table, const Property &primary_prop, ValueType primary_value); inline void verify_attached(); }; @@ -137,6 +143,13 @@ namespace realm { const std::string property_name; }; + class MissingPrimaryKeyException : public std::runtime_error + { + public: + MissingPrimaryKeyException(const std::string object_type, const std::string message) : std::runtime_error(message), object_type(object_type) {} + const std::string object_type; + }; + class MutationOutsideTransactionException : public std::runtime_error { public: @@ -301,16 +314,11 @@ namespace realm { size_t row_index = realm::not_found; realm::TableRef table = ObjectStore::table_for_object_type(realm->read_group(), object_schema.name); const Property *primary_prop = object_schema.primary_key_property(); + if (primary_prop) { // search for existing object based on primary key type ValueType primary_value = Accessor::dict_value_for_key(ctx, value, object_schema.primary_key); - if (primary_prop->type == PropertyType::String) { - auto primary_string = Accessor::to_string(ctx, primary_value); - row_index = table->find_first_string(primary_prop->table_column, primary_string); - } - else { - row_index = table->find_first_int(primary_prop->table_column, Accessor::to_long(ctx, primary_value)); - } + row_index = get_for_primary_key_impl(ctx, table, *primary_prop, primary_value); if (!try_update && row_index != realm::not_found) { throw DuplicatePrimaryKeyValueException(object_schema.name, *primary_prop, @@ -348,7 +356,34 @@ namespace realm { } return object; } - + + template + inline Object Object::get_for_primary_key(ContextType ctx, SharedRealm realm, const ObjectSchema &object_schema, ValueType primary_value) + { + auto primary_prop = object_schema.primary_key_property(); + if (!primary_prop) { + throw MissingPrimaryKeyException(object_schema.name, object_schema.name + " does not have a primary key"); + } + + auto table = ObjectStore::table_for_object_type(realm->read_group(), object_schema.name); + auto row_index = get_for_primary_key_impl(ctx, table, *primary_prop, primary_value); + + return Object(realm, object_schema, row_index == realm::not_found ? Row() : table->get(row_index)); + } + + template + inline size_t Object::get_for_primary_key_impl(ContextType ctx, const ConstTableRef &table, const Property &primary_prop, ValueType primary_value) { + using Accessor = NativeAccessor; + + if (primary_prop.type == PropertyType::String) { + auto primary_string = Accessor::to_string(ctx, primary_value); + return table->find_first_string(primary_prop.table_column, primary_string); + } + else { + return table->find_first_int(primary_prop.table_column, Accessor::to_long(ctx, primary_value)); + } + } + inline void Object::verify_attached() { if (!m_row.is_attached()) { throw InvalidatedObjectException(m_object_schema->name, diff --git a/tests/js/realm-tests.js b/tests/js/realm-tests.js index 628adfde..ec426327 100644 --- a/tests/js/realm-tests.js +++ b/tests/js/realm-tests.js @@ -638,6 +638,43 @@ module.exports = { }); }, + testRealmObjectForPrimaryKey: function() { + var realm = new Realm({schema: [schemas.IntPrimary, schemas.StringPrimary, schemas.TestObject]}); + + realm.write(function() { + realm.create('IntPrimaryObject', {primaryCol: 0, valueCol: 'val0'}); + realm.create('IntPrimaryObject', {primaryCol: 1, valueCol: 'val1'}); + + realm.create('StringPrimaryObject', {primaryCol: '', valueCol: -1}); + realm.create('StringPrimaryObject', {primaryCol: 'val0', valueCol: 0}); + realm.create('StringPrimaryObject', {primaryCol: 'val1', valueCol: 1}); + + realm.create('TestObject', {doubleCol: 0}); + }); + + TestCase.assertEqual(realm.objectForPrimaryKey('IntPrimaryObject', -1), undefined); + TestCase.assertEqual(realm.objectForPrimaryKey('IntPrimaryObject', 0).valueCol, 'val0'); + TestCase.assertEqual(realm.objectForPrimaryKey('IntPrimaryObject', 1).valueCol, 'val1'); + + TestCase.assertEqual(realm.objectForPrimaryKey('StringPrimaryObject', 'invalid'), undefined); + TestCase.assertEqual(realm.objectForPrimaryKey('StringPrimaryObject', '').valueCol, -1); + TestCase.assertEqual(realm.objectForPrimaryKey('StringPrimaryObject', 'val0').valueCol, 0); + TestCase.assertEqual(realm.objectForPrimaryKey('StringPrimaryObject', 'val1').valueCol, 1); + + TestCase.assertThrows(function() { + realm.objectForPrimaryKey('TestObject', 0); + }); + TestCase.assertThrows(function() { + realm.objectForPrimaryKey(); + }); + TestCase.assertThrows(function() { + realm.objectForPrimaryKey('IntPrimary'); + }); + TestCase.assertThrows(function() { + realm.objectForPrimaryKey('InvalidClass', 0); + }); + }, + testNotifications: function() { var realm = new Realm({schema: []}); var notificationCount = 0; diff --git a/tests/js/schemas.js b/tests/js/schemas.js index 888ef44a..76482b31 100644 --- a/tests/js/schemas.js +++ b/tests/js/schemas.js @@ -106,6 +106,15 @@ exports.IntPrimary = { } }; +exports.StringPrimary = { + name: 'StringPrimaryObject', + primaryKey: 'primaryCol', + properties: { + primaryCol: Realm.Types.STRING, + valueCol: Realm.Types.INT, + } +}; + exports.AllTypes = { name: 'AllTypesObject', primaryKey: 'primaryCol', From 3c657c3bbfd55a02ebe17799380f8f364c4cc723 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Fri, 3 Jun 2016 16:59:50 -0700 Subject: [PATCH 07/21] Update docs and CHANGELOG with objectForPrimaryKey --- CHANGELOG.md | 1 + docs/realm.js | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42fd136d..4bc4b402 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ x.x.x Release notes (yyyy-MM-dd) ### Enhancements * Added `isValid()` method to `List` and `Results` to check for deleleted or invalidated objects +* Added `objectForPrimaryKey(type, key)` method to `Realm` ### Bugfixes * None diff --git a/docs/realm.js b/docs/realm.js index ade8d8a8..780e3243 100644 --- a/docs/realm.js +++ b/docs/realm.js @@ -106,6 +106,16 @@ class Realm { */ objects(type) {} + /** + * Searches for a Realm object by its primary key. + * @param {Realm~ObjectType} type - The type of Realm object to search for. + * @param {number|string} key - The primary key value of the object to search for. + * @throws {Error} If type passed into this method is invalid or if the object type did + * not have a `primaryKey` specified in its {@link Realm~ObjectSchema ObjectSchema}. + * @returns {Realm.Object|undefined} if no object is found. + */ + objectForPrimaryKey(type, key) {} + /** * Add a listener `callback` for the specified event `name`. * @param {string} name - The name of event that should cause the callback to be called. From c8df1cddec727564aafe58b7f0f16ef083d9bac9 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Tue, 7 Jun 2016 18:20:51 -0700 Subject: [PATCH 08/21] Update projects to React Native 0.27.1 --- examples/ReactExample/.flowconfig | 50 +++++++++++++++---- .../android/app/proguard-rules.pro | 10 ++-- examples/ReactExample/package.json | 4 +- examples/ReactNativeBenchmarks/.flowconfig | 50 +++++++++++++++---- .../android/app/proguard-rules.pro | 10 ++-- examples/ReactNativeBenchmarks/package.json | 4 +- tests/react-test-app/.flowconfig | 50 +++++++++++++++---- .../android/app/proguard-rules.pro | 10 ++-- tests/react-test-app/package.json | 4 +- 9 files changed, 138 insertions(+), 54 deletions(-) diff --git a/examples/ReactExample/.flowconfig b/examples/ReactExample/.flowconfig index c3edaf94..45fd3ccb 100644 --- a/examples/ReactExample/.flowconfig +++ b/examples/ReactExample/.flowconfig @@ -15,11 +15,6 @@ # Ignore react and fbjs where there are overlaps, but don't ignore # anything that react-native relies on .*/node_modules/fbjs/lib/Map.js -.*/node_modules/fbjs/lib/Promise.js -.*/node_modules/fbjs/lib/fetch.js -.*/node_modules/fbjs/lib/ExecutionEnvironment.js -.*/node_modules/fbjs/lib/isEmpty.js -.*/node_modules/fbjs/lib/crc32.js .*/node_modules/fbjs/lib/ErrorUtils.js # Flow has a built-in definition for the 'react' module which we prefer to use @@ -28,6 +23,11 @@ .*/node_modules/react/lib/React.js .*/node_modules/react/lib/ReactDOM.js +.*/__mocks__/.* +.*/__tests__/.* + +.*/commoner/test/source/widget/share.js + # Ignore commoner tests .*/node_modules/commoner/test/.* @@ -40,26 +40,58 @@ # Ignore Website .*/website/.* +# Ignore generators +.*/local-cli/generator.* + +# Ignore BUCK generated folders +.*\.buckd/ + +# Ignore RNPM +.*/local-cli/rnpm/.* + +.*/node_modules/is-my-json-valid/test/.*\.json +.*/node_modules/iconv-lite/encodings/tables/.*\.json +.*/node_modules/y18n/test/.*\.json +.*/node_modules/spdx-license-ids/spdx-license-ids.json +.*/node_modules/spdx-exceptions/index.json +.*/node_modules/resolve/test/subdirs/node_modules/a/b/c/x.json +.*/node_modules/resolve/lib/core.json +.*/node_modules/jsonparse/samplejson/.*\.json +.*/node_modules/json5/test/.*\.json +.*/node_modules/ua-parser-js/test/.*\.json +.*/node_modules/builtin-modules/builtin-modules.json +.*/node_modules/binary-extensions/binary-extensions.json +.*/node_modules/url-regex/tlds.json +.*/node_modules/joi/.*\.json +.*/node_modules/isemail/.*\.json +.*/node_modules/tr46/.*\.json + + [include] [libs] node_modules/react-native/Libraries/react-native/react-native-interface.js +node_modules/react-native/flow +flow/ [options] module.system=haste +esproposal.class_static_fields=enable +esproposal.class_instance_fields=enable + munge_underscores=true module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub' -module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\)$' -> 'RelativeImageStub' +module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub' suppress_type=$FlowIssue suppress_type=$FlowFixMe suppress_type=$FixMe -suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(2[0-1]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) -suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(2[0-1]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ +suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(2[0-5]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) +suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(2[0-5]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy [version] -0.21.0 +^0.25.0 diff --git a/examples/ReactExample/android/app/proguard-rules.pro b/examples/ReactExample/android/app/proguard-rules.pro index 7d72e469..9852871b 100644 --- a/examples/ReactExample/android/app/proguard-rules.pro +++ b/examples/ReactExample/android/app/proguard-rules.pro @@ -51,9 +51,9 @@ -keepattributes Signature -keepattributes *Annotation* --keep class com.squareup.okhttp.** { *; } --keep interface com.squareup.okhttp.** { *; } --dontwarn com.squareup.okhttp.** +-keep class okhttp3.** { *; } +-keep interface okhttp3.** { *; } +-dontwarn okhttp3.** # okio @@ -61,7 +61,3 @@ -dontwarn java.nio.file.* -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement -dontwarn okio.** - -# stetho - --dontwarn com.facebook.stetho.** diff --git a/examples/ReactExample/package.json b/examples/ReactExample/package.json index 22a0147e..b1555215 100644 --- a/examples/ReactExample/package.json +++ b/examples/ReactExample/package.json @@ -6,8 +6,8 @@ "start": "react-native start" }, "dependencies": { - "react": "15.0.2", - "react-native": "^0.26.2", + "react": "15.1.0", + "react-native": "^0.27.1", "realm": "file:../.." } } diff --git a/examples/ReactNativeBenchmarks/.flowconfig b/examples/ReactNativeBenchmarks/.flowconfig index c3edaf94..45fd3ccb 100644 --- a/examples/ReactNativeBenchmarks/.flowconfig +++ b/examples/ReactNativeBenchmarks/.flowconfig @@ -15,11 +15,6 @@ # Ignore react and fbjs where there are overlaps, but don't ignore # anything that react-native relies on .*/node_modules/fbjs/lib/Map.js -.*/node_modules/fbjs/lib/Promise.js -.*/node_modules/fbjs/lib/fetch.js -.*/node_modules/fbjs/lib/ExecutionEnvironment.js -.*/node_modules/fbjs/lib/isEmpty.js -.*/node_modules/fbjs/lib/crc32.js .*/node_modules/fbjs/lib/ErrorUtils.js # Flow has a built-in definition for the 'react' module which we prefer to use @@ -28,6 +23,11 @@ .*/node_modules/react/lib/React.js .*/node_modules/react/lib/ReactDOM.js +.*/__mocks__/.* +.*/__tests__/.* + +.*/commoner/test/source/widget/share.js + # Ignore commoner tests .*/node_modules/commoner/test/.* @@ -40,26 +40,58 @@ # Ignore Website .*/website/.* +# Ignore generators +.*/local-cli/generator.* + +# Ignore BUCK generated folders +.*\.buckd/ + +# Ignore RNPM +.*/local-cli/rnpm/.* + +.*/node_modules/is-my-json-valid/test/.*\.json +.*/node_modules/iconv-lite/encodings/tables/.*\.json +.*/node_modules/y18n/test/.*\.json +.*/node_modules/spdx-license-ids/spdx-license-ids.json +.*/node_modules/spdx-exceptions/index.json +.*/node_modules/resolve/test/subdirs/node_modules/a/b/c/x.json +.*/node_modules/resolve/lib/core.json +.*/node_modules/jsonparse/samplejson/.*\.json +.*/node_modules/json5/test/.*\.json +.*/node_modules/ua-parser-js/test/.*\.json +.*/node_modules/builtin-modules/builtin-modules.json +.*/node_modules/binary-extensions/binary-extensions.json +.*/node_modules/url-regex/tlds.json +.*/node_modules/joi/.*\.json +.*/node_modules/isemail/.*\.json +.*/node_modules/tr46/.*\.json + + [include] [libs] node_modules/react-native/Libraries/react-native/react-native-interface.js +node_modules/react-native/flow +flow/ [options] module.system=haste +esproposal.class_static_fields=enable +esproposal.class_instance_fields=enable + munge_underscores=true module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub' -module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\)$' -> 'RelativeImageStub' +module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub' suppress_type=$FlowIssue suppress_type=$FlowFixMe suppress_type=$FixMe -suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(2[0-1]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) -suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(2[0-1]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ +suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(2[0-5]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) +suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(2[0-5]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy [version] -0.21.0 +^0.25.0 diff --git a/examples/ReactNativeBenchmarks/android/app/proguard-rules.pro b/examples/ReactNativeBenchmarks/android/app/proguard-rules.pro index 7d72e469..9852871b 100644 --- a/examples/ReactNativeBenchmarks/android/app/proguard-rules.pro +++ b/examples/ReactNativeBenchmarks/android/app/proguard-rules.pro @@ -51,9 +51,9 @@ -keepattributes Signature -keepattributes *Annotation* --keep class com.squareup.okhttp.** { *; } --keep interface com.squareup.okhttp.** { *; } --dontwarn com.squareup.okhttp.** +-keep class okhttp3.** { *; } +-keep interface okhttp3.** { *; } +-dontwarn okhttp3.** # okio @@ -61,7 +61,3 @@ -dontwarn java.nio.file.* -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement -dontwarn okio.** - -# stetho - --dontwarn com.facebook.stetho.** diff --git a/examples/ReactNativeBenchmarks/package.json b/examples/ReactNativeBenchmarks/package.json index 35b67f07..fffbe254 100644 --- a/examples/ReactNativeBenchmarks/package.json +++ b/examples/ReactNativeBenchmarks/package.json @@ -6,8 +6,8 @@ "start": "react-native start" }, "dependencies": { - "react": "15.0.2", - "react-native": "^0.26.2", + "react": "15.1.0", + "react-native": "^0.27.1", "react-native-sqlite-storage": "^2.1.3", "react-native-store": "^0.4.1", "realm": "file:../.." diff --git a/tests/react-test-app/.flowconfig b/tests/react-test-app/.flowconfig index c3edaf94..45fd3ccb 100644 --- a/tests/react-test-app/.flowconfig +++ b/tests/react-test-app/.flowconfig @@ -15,11 +15,6 @@ # Ignore react and fbjs where there are overlaps, but don't ignore # anything that react-native relies on .*/node_modules/fbjs/lib/Map.js -.*/node_modules/fbjs/lib/Promise.js -.*/node_modules/fbjs/lib/fetch.js -.*/node_modules/fbjs/lib/ExecutionEnvironment.js -.*/node_modules/fbjs/lib/isEmpty.js -.*/node_modules/fbjs/lib/crc32.js .*/node_modules/fbjs/lib/ErrorUtils.js # Flow has a built-in definition for the 'react' module which we prefer to use @@ -28,6 +23,11 @@ .*/node_modules/react/lib/React.js .*/node_modules/react/lib/ReactDOM.js +.*/__mocks__/.* +.*/__tests__/.* + +.*/commoner/test/source/widget/share.js + # Ignore commoner tests .*/node_modules/commoner/test/.* @@ -40,26 +40,58 @@ # Ignore Website .*/website/.* +# Ignore generators +.*/local-cli/generator.* + +# Ignore BUCK generated folders +.*\.buckd/ + +# Ignore RNPM +.*/local-cli/rnpm/.* + +.*/node_modules/is-my-json-valid/test/.*\.json +.*/node_modules/iconv-lite/encodings/tables/.*\.json +.*/node_modules/y18n/test/.*\.json +.*/node_modules/spdx-license-ids/spdx-license-ids.json +.*/node_modules/spdx-exceptions/index.json +.*/node_modules/resolve/test/subdirs/node_modules/a/b/c/x.json +.*/node_modules/resolve/lib/core.json +.*/node_modules/jsonparse/samplejson/.*\.json +.*/node_modules/json5/test/.*\.json +.*/node_modules/ua-parser-js/test/.*\.json +.*/node_modules/builtin-modules/builtin-modules.json +.*/node_modules/binary-extensions/binary-extensions.json +.*/node_modules/url-regex/tlds.json +.*/node_modules/joi/.*\.json +.*/node_modules/isemail/.*\.json +.*/node_modules/tr46/.*\.json + + [include] [libs] node_modules/react-native/Libraries/react-native/react-native-interface.js +node_modules/react-native/flow +flow/ [options] module.system=haste +esproposal.class_static_fields=enable +esproposal.class_instance_fields=enable + munge_underscores=true module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub' -module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\)$' -> 'RelativeImageStub' +module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub' suppress_type=$FlowIssue suppress_type=$FlowFixMe suppress_type=$FixMe -suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(2[0-1]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) -suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(2[0-1]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ +suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(2[0-5]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) +suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(2[0-5]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy [version] -0.21.0 +^0.25.0 diff --git a/tests/react-test-app/android/app/proguard-rules.pro b/tests/react-test-app/android/app/proguard-rules.pro index 7d72e469..9852871b 100644 --- a/tests/react-test-app/android/app/proguard-rules.pro +++ b/tests/react-test-app/android/app/proguard-rules.pro @@ -51,9 +51,9 @@ -keepattributes Signature -keepattributes *Annotation* --keep class com.squareup.okhttp.** { *; } --keep interface com.squareup.okhttp.** { *; } --dontwarn com.squareup.okhttp.** +-keep class okhttp3.** { *; } +-keep interface okhttp3.** { *; } +-dontwarn okhttp3.** # okio @@ -61,7 +61,3 @@ -dontwarn java.nio.file.* -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement -dontwarn okio.** - -# stetho - --dontwarn com.facebook.stetho.** diff --git a/tests/react-test-app/package.json b/tests/react-test-app/package.json index 6e9f6953..21802055 100644 --- a/tests/react-test-app/package.json +++ b/tests/react-test-app/package.json @@ -6,8 +6,8 @@ "start": "react-native start" }, "dependencies": { - "react": "15.0.2", - "react-native": "^0.26.2", + "react": "15.1.0", + "react-native": "^0.27.1", "react-native-fs": "^1.1.0", "xmlbuilder": "^4.2.1", "realm": "file:../..", From 81feca0ce91cb33482629919ef8164dd12a392fa Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Wed, 8 Jun 2016 11:22:12 -0700 Subject: [PATCH 09/21] fix for setting properties to objects from other realms --- CHANGELOG.md | 2 +- src/js_object_accessor.hpp | 5 ++++- tests/js/object-tests.js | 11 +++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42fd136d..f56922bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ x.x.x Release notes (yyyy-MM-dd) * Added `isValid()` method to `List` and `Results` to check for deleleted or invalidated objects ### Bugfixes -* None +* Fix for crash when setting object properties to objects from other Realms 0.13.2 Release notes (2016-5-26) ============================================================= diff --git a/src/js_object_accessor.hpp b/src/js_object_accessor.hpp index b6e8eb40..37448925 100644 --- a/src/js_object_accessor.hpp +++ b/src/js_object_accessor.hpp @@ -106,7 +106,10 @@ struct NativeAccessor { static size_t to_object_index(ContextType ctx, SharedRealm realm, ValueType &value, const std::string &type, bool try_update) { ObjectType object = Value::validated_to_object(ctx, value); if (Object::template is_instance>(ctx, object)) { - return get_internal>(object)->row().get_index(); + auto realm_object = get_internal>(object); + if (realm_object->realm() == realm) { + return realm_object->row().get_index(); + } } auto object_schema = realm->config().schema->find(type); diff --git a/tests/js/object-tests.js b/tests/js/object-tests.js index 86cb626a..a446f8f7 100644 --- a/tests/js/object-tests.js +++ b/tests/js/object-tests.js @@ -328,6 +328,17 @@ module.exports = { TestCase.assertEqual(obj.arrayCol[0].doubleCol, 3); TestCase.assertEqual(obj.arrayCol[1].doubleCol, 1); TestCase.assertEqual(obj.arrayCol[2].doubleCol, 2); + + // set object from another realm + var another = new Realm({path: 'another.realm', schema: realm.schema}); + var anotherObj; + another.write(function() { + anotherObj = another.create('TestObject', {doubleCol: 3}); + }); + realm.write(function() { + obj.objectCol = anotherObj; + }); + TestCase.assertEqual(obj.objectCol.doubleCol, 3); }, testEnumerablePropertyNames: function() { var realm = new Realm({schema: [schemas.BasicTypes]}); From cdcb99a502b8643f113f0818f4979b34b3e8d5f7 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Thu, 9 Jun 2016 13:07:05 -0700 Subject: [PATCH 10/21] Improvements from PR feedback --- lib/browser/index.js | 25 ++++++++++--------------- src/js_realm.hpp | 1 - 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/lib/browser/index.js b/lib/browser/index.js index b189a7e4..add249a2 100644 --- a/lib/browser/index.js +++ b/lib/browser/index.js @@ -56,6 +56,13 @@ function setupRealm(realm, realmId) { }); } +function getObjectType(realm, type) { + if (typeof type == 'function') { + return objects.typeForConstructor(realm[keys.realm], type); + } + return type; +} + export default class Realm { constructor(config) { let schemas = typeof config == 'object' && config.schema; @@ -90,30 +97,18 @@ export default class Realm { } create(type, ...args) { - if (typeof type == 'function') { - type = objects.typeForConstructor(this[keys.realm], type); - } - let method = util.createMethod(objectTypes.REALM, 'create', true); - return method.apply(this, [type, ...args]); + return method.apply(this, [getObjectType(this, type), ...args]); } objects(type, ...args) { - if (typeof type == 'function') { - type = objects.typeForConstructor(this[keys.realm], type); - } - let method = util.createMethod(objectTypes.REALM, 'objects'); - return method.apply(this, [type, ...args]); + return method.apply(this, [getObjectType(this, type), ...args]); } objectForPrimaryKey(type, ...args) { - if (typeof type == 'function') { - type = objects.typeForConstructor(this[keys.realm], type); - } - let method = util.createMethod(objectTypes.REALM, 'objectForPrimaryKey'); - return method.apply(this, [type, ...args]); + return method.apply(this, [getObjectType(this, type), ...args]); } } diff --git a/src/js_realm.hpp b/src/js_realm.hpp index 271f7fa4..c5f13233 100644 --- a/src/js_realm.hpp +++ b/src/js_realm.hpp @@ -208,7 +208,6 @@ public: return name; } - // converts constructor object or type name to type name static const ObjectSchema& validated_object_schema_for_value(ContextType ctx, const SharedRealm &realm, const ValueType &value) { std::string object_type; From cd20d870dde588f72356d3edff8dada6d0f8d152 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Thu, 9 Jun 2016 13:59:49 -0700 Subject: [PATCH 11/21] Fix crash from querying with object from another Realm --- src/js_object_accessor.hpp | 8 ++++++-- src/js_results.hpp | 2 +- src/object-store/src/object_accessor.hpp | 2 +- src/object-store/src/parser/query_builder.hpp | 6 ++++-- tests/js/results-tests.js | 17 ++++++++++++++++- 5 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/js_object_accessor.hpp b/src/js_object_accessor.hpp index 37448925..cccf6e23 100644 --- a/src/js_object_accessor.hpp +++ b/src/js_object_accessor.hpp @@ -120,10 +120,14 @@ struct NativeAccessor { auto child = realm::Object::create(ctx, realm, *object_schema, static_cast(object), try_update); return child.row().get_index(); } - static size_t to_existing_object_index(ContextType ctx, ValueType &value) { + static size_t to_existing_object_index(ContextType ctx, SharedRealm realm, ValueType &value) { ObjectType object = Value::validated_to_object(ctx, value); if (Object::template is_instance>(ctx, object)) { - return get_internal>(object)->row().get_index(); + auto realm_object = get_internal>(object); + if (realm_object->realm() == realm) { + return realm_object->row().get_index(); + } + throw std::runtime_error("Realm object is from another Realm"); } throw std::runtime_error("object is not a Realm Object"); } diff --git a/src/js_results.hpp b/src/js_results.hpp index 640d67fb..97459bbd 100644 --- a/src/js_results.hpp +++ b/src/js_results.hpp @@ -126,7 +126,7 @@ typename T::Object ResultsClass::create_filtered(ContextType ctx, const U &co } parser::Predicate predicate = parser::parse(query_string); - query_builder::ArgumentConverter converter(ctx, args); + query_builder::ArgumentConverter converter(ctx, realm, args); query_builder::apply_predicate(query, predicate, converter, *realm->config().schema, object_schema.name); return create_instance(ctx, realm, object_schema, std::move(query)); diff --git a/src/object-store/src/object_accessor.hpp b/src/object-store/src/object_accessor.hpp index c20282b6..61360f10 100644 --- a/src/object-store/src/object_accessor.hpp +++ b/src/object-store/src/object_accessor.hpp @@ -101,7 +101,7 @@ namespace realm { static ValueType from_object(ContextType ctx, Object); // object index for an existing object - static size_t to_existing_object_index(ContextType ctx, ValueType &val); + static size_t to_existing_object_index(ContextType ctx, SharedRealm realm, ValueType &val); // list value acessors static size_t list_size(ContextType ctx, ValueType &val); diff --git a/src/object-store/src/parser/query_builder.hpp b/src/object-store/src/parser/query_builder.hpp index f9dba1bd..ae491072 100644 --- a/src/object-store/src/parser/query_builder.hpp +++ b/src/object-store/src/parser/query_builder.hpp @@ -50,7 +50,8 @@ class Arguments { template class ArgumentConverter : public Arguments { public: - ArgumentConverter(ContextType context, std::vector arguments) : m_arguments(arguments), m_ctx(context) {} + ArgumentConverter(ContextType context, SharedRealm realm, std::vector arguments) + : m_arguments(arguments), m_ctx(context), m_realm(std::move(realm)) {} using Accessor = realm::NativeAccessor; virtual bool bool_for_argument(size_t argument_index) { return Accessor::to_bool(m_ctx, argument_at(argument_index)); } @@ -60,12 +61,13 @@ class ArgumentConverter : public Arguments { virtual std::string string_for_argument(size_t argument_index) { return Accessor::to_string(m_ctx, argument_at(argument_index)); } virtual std::string binary_for_argument(size_t argument_index) { return Accessor::to_binary(m_ctx, argument_at(argument_index)); } virtual Timestamp timestamp_for_argument(size_t argument_index) { return Accessor::to_timestamp(m_ctx, argument_at(argument_index)); } - virtual size_t object_index_for_argument(size_t argument_index) { return Accessor::to_existing_object_index(m_ctx, argument_at(argument_index)); } + virtual size_t object_index_for_argument(size_t argument_index) { return Accessor::to_existing_object_index(m_ctx, m_realm, argument_at(argument_index)); } virtual bool is_argument_null(size_t argument_index) { return Accessor::is_null(m_ctx, argument_at(argument_index)); } private: std::vector m_arguments; ContextType m_ctx; + SharedRealm m_realm; ValueType &argument_at(size_t index) { if (index >= m_arguments.size()) { diff --git a/tests/js/results-tests.js b/tests/js/results-tests.js index 24b3822f..ad3636eb 100644 --- a/tests/js/results-tests.js +++ b/tests/js/results-tests.js @@ -130,6 +130,7 @@ module.exports = { testResultsFiltered: function() { var realm = new Realm({schema: [schemas.PersonObject, schemas.DefaultValues, schemas.TestObject]}); + realm.write(function() { realm.create('PersonObject', {name: 'Ari', age: 10}); realm.create('PersonObject', {name: 'Tim', age: 11}); @@ -155,9 +156,13 @@ module.exports = { TestCase.assertEqual(realm.objects('PersonObject').filtered('name = $0', 'Tim').length, 1); TestCase.assertEqual(realm.objects('PersonObject').filtered('age > $1 && age < $0', 13, 10).length, 3); + TestCase.assertThrows(function() { realm.objects('PersonObject').filtered('age > $2 && age < $0', 13, 10) }); + TestCase.assertThrows(function() { + realm.objects('PersonObject').filtered("invalidQuery"); + }); realm.write(function() { realm.create('DefaultValuesObject', {'dateCol': new Date(3)}); @@ -167,9 +172,19 @@ module.exports = { TestCase.assertEqual(realm.objects('DefaultValuesObject').filtered('dateCol > $0', new Date(4)).length, 1); TestCase.assertEqual(realm.objects('DefaultValuesObject').filtered('dateCol <= $0', new Date(4)).length, 2); + }, + + testResultsFilteredByForeignObject: function() { + var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]}); + var realm2 = new Realm({path: '2.realm', schema: realm.schema}); + var object; + + realm2.write(function() { + object = realm2.create('TestObject', {doubleCol: 1}); + }); TestCase.assertThrows(function() { - realm.objects('PersonObject').filtered("invalidQuery"); + realm.objects('LinkTypesObject').filtered('objectCol = $0', object); }); }, From 721b563658aaf05159f489eef7bc62fea017fe05 Mon Sep 17 00:00:00 2001 From: Makoto Yamazaki Date: Sat, 11 Jun 2016 10:19:27 +0900 Subject: [PATCH 12/21] update Realm logo in README (#481) --- logo.png | Bin 6417 -> 7897 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/logo.png b/logo.png index cbe78177244f3a49f1f750d05739cd932fd55a78..c64d652d2d2cff43099f2dc81bcf3ce18b961095 100644 GIT binary patch literal 7897 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 From 2b48ebb30ab0dafc254bb4df22b96223ddb2c782 Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Mon, 13 Jun 2016 14:07:50 -0700 Subject: [PATCH 13/21] negate if statements --- src/js_object_accessor.hpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/js_object_accessor.hpp b/src/js_object_accessor.hpp index cccf6e23..bcfc06fb 100644 --- a/src/js_object_accessor.hpp +++ b/src/js_object_accessor.hpp @@ -122,14 +122,16 @@ struct NativeAccessor { } static size_t to_existing_object_index(ContextType ctx, SharedRealm realm, ValueType &value) { ObjectType object = Value::validated_to_object(ctx, value); - if (Object::template is_instance>(ctx, object)) { - auto realm_object = get_internal>(object); - if (realm_object->realm() == realm) { - return realm_object->row().get_index(); - } - throw std::runtime_error("Realm object is from another Realm"); + if (!Object::template is_instance>(ctx, object)) { + throw std::runtime_error("object is not a Realm Object"); } - throw std::runtime_error("object is not a Realm Object"); + + auto realm_object = get_internal>(object); + if (realm_object->realm() != realm) { + throw std::runtime_error("Realm object is from another Realm"); + + } + return realm_object->row().get_index(); } static ValueType from_object(ContextType ctx, realm::Object realm_object) { return RealmObjectClass::create_instance(ctx, std::move(realm_object)); From 0a4e0665ae89dc0aeca9055c9486d5019dcf6c55 Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Mon, 13 Jun 2016 14:46:26 -0700 Subject: [PATCH 14/21] fixes for typos and added upsert test --- src/object-store/src/binding_context.hpp | 2 +- src/object-store/src/object_accessor.hpp | 2 +- tests/js/realm-tests.js | 15 ++++++++++++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/object-store/src/binding_context.hpp b/src/object-store/src/binding_context.hpp index d57ce541..8290144b 100644 --- a/src/object-store/src/binding_context.hpp +++ b/src/object-store/src/binding_context.hpp @@ -80,7 +80,7 @@ public: struct ObserverState; - // Override this function if you want to recieve detailed information about + // Override this function if you want to receive detailed information about // external changes to a specific set of objects. // This is called before each operation which may advance the read // transaction to include diff --git a/src/object-store/src/object_accessor.hpp b/src/object-store/src/object_accessor.hpp index f57f42e7..6becf0bd 100644 --- a/src/object-store/src/object_accessor.hpp +++ b/src/object-store/src/object_accessor.hpp @@ -322,7 +322,7 @@ namespace realm { if (!try_update && row_index != realm::not_found) { throw DuplicatePrimaryKeyValueException(object_schema.name, *primary_prop, - "Attempting to create an object of type '" + object_schema.name + "' with an exising primary key value."); + "Attempting to create an object of type '" + object_schema.name + "' with an existing primary key value."); } } diff --git a/tests/js/realm-tests.js b/tests/js/realm-tests.js index ec426327..6a9ba6b8 100644 --- a/tests/js/realm-tests.js +++ b/tests/js/realm-tests.js @@ -273,7 +273,7 @@ module.exports = { }, testRealmCreateUpsert: function() { - var realm = new Realm({schema: [schemas.IntPrimary, schemas.AllTypes, schemas.TestObject]}); + var realm = new Realm({schema: [schemas.IntPrimary, schemas.StringPrimary, schemas.AllTypes, schemas.TestObject]}); realm.write(function() { var values = { primaryCol: '0', @@ -360,6 +360,19 @@ module.exports = { realm.create('AllTypesObject', {primaryCol: '1', objectCol: null}, true); TestCase.assertEqual(obj0.objectCol, null); TestCase.assertEqual(obj1.objectCol, null); + + // test with string primaries + var obj =realm.create('StringPrimaryObject', { + primaryCol: '0', + valueCol: 0 + }); + TestCase.assertEqual(obj.valueCol, 0); + + realm.create('StringPrimaryObject', { + primaryCol: '0', + valueCol: 1 + }, true); + TestCase.assertEqual(obj.valueCol, 1); }); }, From 2384cc40361b040b59bb0d7e5d7dfcdbe6e60437 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Wed, 4 May 2016 15:38:29 -0700 Subject: [PATCH 15/21] Reset Realm.defaultPath in testDefaultPath Or else the rest of the tests use the new default path! --- tests/js/realm-tests.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tests/js/realm-tests.js b/tests/js/realm-tests.js index 6a9ba6b8..fe966347 100644 --- a/tests/js/realm-tests.js +++ b/tests/js/realm-tests.js @@ -145,14 +145,19 @@ module.exports = { }, testDefaultPath: function() { + var defaultPath = Realm.defaultPath; var defaultRealm = new Realm({schema: []}); TestCase.assertEqual(defaultRealm.path, Realm.defaultPath); - var newPath = Realm.defaultPath.substring(0, Realm.defaultPath.lastIndexOf("/") + 1) + 'default2.realm'; - Realm.defaultPath = newPath; - defaultRealm = new Realm({schema: []}); - TestCase.assertEqual(defaultRealm.path, newPath, "should use updated default realm path"); - TestCase.assertEqual(Realm.defaultPath, newPath, "defaultPath should have been updated"); + try { + var newPath = Realm.defaultPath.substring(0, defaultPath.lastIndexOf('/') + 1) + 'default2.realm'; + Realm.defaultPath = newPath; + defaultRealm = new Realm({schema: []}); + TestCase.assertEqual(defaultRealm.path, newPath, "should use updated default realm path"); + TestCase.assertEqual(Realm.defaultPath, newPath, "defaultPath should have been updated"); + } finally { + Realm.defaultPath = defaultPath; + } }, testRealmSchemaVersion: function() { From 9bcb30e86d84daf29dc3f41a3f405bfc6312c9a3 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Wed, 1 Jun 2016 02:14:46 -0700 Subject: [PATCH 16/21] Add missing source files to RealmNode target --- src/RealmJS.xcodeproj/project.pbxproj | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/RealmJS.xcodeproj/project.pbxproj b/src/RealmJS.xcodeproj/project.pbxproj index bafed5b7..6f11a3cc 100644 --- a/src/RealmJS.xcodeproj/project.pbxproj +++ b/src/RealmJS.xcodeproj/project.pbxproj @@ -70,6 +70,11 @@ F674784A1CC81F1900F9273C /* platform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F67478481CC81F1300F9273C /* platform.cpp */; }; F68A278C1BC2722A0063D40A /* RJSModuleLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = F68A278B1BC2722A0063D40A /* RJSModuleLoader.m */; }; F6BCCFE21C8380A400FE31AE /* lib in Resources */ = {isa = PBXBuildFile; fileRef = F6BCCFDF1C83809A00FE31AE /* lib */; }; + F6E931BA1CFEAE170016AF14 /* collection_notifications.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02414B961CE6AADD00A8669F /* collection_notifications.cpp */; }; + F6E931BB1CFEAE310016AF14 /* collection_change_builder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02414B991CE6AAEF00A8669F /* collection_change_builder.cpp */; }; + F6E931BC1CFEAE340016AF14 /* collection_notifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02414B9B1CE6AAEF00A8669F /* collection_notifier.cpp */; }; + F6E931BD1CFEAE370016AF14 /* list_notifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02414B9D1CE6AAEF00A8669F /* list_notifier.cpp */; }; + F6E931BE1CFEAE3A0016AF14 /* results_notifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02414B9F1CE6AAEF00A8669F /* results_notifier.cpp */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -748,16 +753,21 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + F6E931BA1CFEAE170016AF14 /* collection_notifications.cpp in Sources */, F60102D31CBB966E00EC01BA /* js_realm.cpp in Sources */, F60102D61CBB96B400EC01BA /* object_schema.cpp in Sources */, F60102D41CBB96AB00EC01BA /* index_set.cpp in Sources */, F60102DB1CBB96C600EC01BA /* parser.cpp in Sources */, + F6E931BB1CFEAE310016AF14 /* collection_change_builder.cpp in Sources */, F60102D51CBB96AE00EC01BA /* list.cpp in Sources */, + F6E931BC1CFEAE340016AF14 /* collection_notifier.cpp in Sources */, F60102DC1CBB96C900EC01BA /* query_builder.cpp in Sources */, F60102DD1CBB96CC00EC01BA /* external_commit_helper.cpp in Sources */, F63117F01CEB0D5F00ECB2DE /* weak_realm_notifier.cpp in Sources */, F60102E11CBB96DD00EC01BA /* transact_log_handler.cpp in Sources */, + F6E931BE1CFEAE3A0016AF14 /* results_notifier.cpp in Sources */, F60102D71CBB96B800EC01BA /* object_store.cpp in Sources */, + F6E931BD1CFEAE370016AF14 /* list_notifier.cpp in Sources */, F60102DA1CBB96C300EC01BA /* shared_realm.cpp in Sources */, F60102E01CBB96D900EC01BA /* realm_coordinator.cpp in Sources */, F60102EA1CBCAFC300EC01BA /* node_dummy.cpp in Sources */, From 43f7329047159cef13ce334ec710aec49c7201cd Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Wed, 1 Jun 2016 09:40:40 -0700 Subject: [PATCH 17/21] Remove confusing, unnecessary typedef This is not used anywhere. --- src/jsc/jsc_types.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/jsc/jsc_types.hpp b/src/jsc/jsc_types.hpp index 07c36e48..9eca89cd 100644 --- a/src/jsc/jsc_types.hpp +++ b/src/jsc/jsc_types.hpp @@ -30,7 +30,6 @@ namespace jsc { struct Types { using Context = JSContextRef; using GlobalContext = JSGlobalContextRef; - using ClassDefinition = JSClassRef; using Value = JSValueRef; using Object = JSObjectRef; using String = JSStringRef; From 6d524107e07ed89084900b4b701de713879d586c Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Wed, 1 Jun 2016 09:42:17 -0700 Subject: [PATCH 18/21] Silence warnings about member function pointers The base ClassDefinition defines its constructor member as null, but some subclass have a static constructor function. This allows both cases to be handled without a warning. --- src/jsc/jsc_class.hpp | 6 +++--- src/node/node_class.hpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/jsc/jsc_class.hpp b/src/jsc/jsc_class.hpp index 0a236219..31e7e28b 100644 --- a/src/jsc/jsc_class.hpp +++ b/src/jsc/jsc_class.hpp @@ -169,7 +169,7 @@ inline JSClassRef ObjectWrap::create_constructor_class() { // This must be set for `typeof constructor` to be 'function'. definition.callAsFunction = call; - if (s_class.constructor) { + if (reinterpret_cast(s_class.constructor)) { definition.callAsConstructor = construct; } if (!s_class.static_methods.empty()) { @@ -226,7 +226,7 @@ inline JSValueRef ObjectWrap::call(JSContextRef ctx, JSObjectRef func } // Classes without a constructor should still be subclassable. - if (s_class.constructor) { + if (reinterpret_cast(s_class.constructor)) { try { s_class.constructor(ctx, this_object, argc, arguments); } @@ -241,7 +241,7 @@ inline JSValueRef ObjectWrap::call(JSContextRef ctx, JSObjectRef func template inline JSObjectRef ObjectWrap::construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef arguments[], JSValueRef* exception) { - if (!s_class.constructor) { + if (!reinterpret_cast(s_class.constructor)) { *exception = jsc::Exception::value(ctx, s_class.name + " is not a constructor"); return nullptr; } diff --git a/src/node/node_class.hpp b/src/node/node_class.hpp index ea95cf98..4072cd3e 100644 --- a/src/node/node_class.hpp +++ b/src/node/node_class.hpp @@ -226,7 +226,7 @@ inline void ObjectWrap::construct(Nan::NAN_METHOD_ARGS_TYPE info) { if (!info.IsConstructCall()) { Nan::ThrowError("Constructor must be called with new"); } - if (s_class.constructor) { + if (reinterpret_cast(s_class.constructor)) { auto isolate = info.GetIsolate(); auto arguments = get_arguments(info); v8::Local this_object = info.This(); From 723b50f6492235c9250fb9818e2927db1d7fbae2 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Thu, 18 Feb 2016 11:19:13 -0800 Subject: [PATCH 19/21] Allow React tests to be async --- tests/js/index.js | 18 ++++++++++++++++-- tests/react-test-app/index.android.js | 2 +- tests/react-test-app/tests/index.js | 16 ++++++++-------- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/tests/js/index.js b/tests/js/index.js index e240b801..c3e84748 100644 --- a/tests/js/index.js +++ b/tests/js/index.js @@ -63,10 +63,24 @@ exports.runTest = function(suiteName, testName) { // Start fresh in case of a crash in a previous run. Realm.clearTestState(); + var promise; try { - testMethod.call(testSuite); + promise = testMethod.call(testSuite); + + // If the test returns a promise, then clear state on success or failure. + if (promise) { + promise.then( + function() { Realm.clearTestState(); }, + function() { Realm.clearTestState(); } + ); + } + + return promise; } finally { - Realm.clearTestState(); + // Synchronously clear state if the test is not async. + if (!promise) { + Realm.clearTestState(); + } } } else if (!testSuite || !(testName in SPECIAL_METHODS)) { throw new Error('Missing test: ' + suiteName + '.' + testName); diff --git a/tests/react-test-app/index.android.js b/tests/react-test-app/index.android.js index da211d31..bd27a8e3 100644 --- a/tests/react-test-app/index.android.js +++ b/tests/react-test-app/index.android.js @@ -48,7 +48,7 @@ async function runTests() { itemTest.att('name', testName); try { - runTest(suiteName, testName); + await runTest(suiteName, testName); } catch (e) { itemTest.ele('error', {'message': ''}, e.message); diff --git a/tests/react-test-app/tests/index.js b/tests/react-test-app/tests/index.js index 2eff1504..d0ef9ad8 100644 --- a/tests/react-test-app/tests/index.js +++ b/tests/react-test-app/tests/index.js @@ -27,10 +27,10 @@ RealmTests.registerTests({ }); // Listen for event to run a particular test. -NativeAppEventEmitter.addListener('realm-run-test', (test) => { +NativeAppEventEmitter.addListener('realm-run-test', async ({suite, name}) => { let error; try { - RealmTests.runTest(test.suite, test.name); + await RealmTests.runTest(suite, name); } catch (e) { error = '' + e; } @@ -50,23 +50,23 @@ export function getTestNames() { return RealmTests.getTestNames(); } -export function runTests() { +export async function runTests() { let testNames = getTestNames(); for (let suiteName in testNames) { console.log('Starting ' + suiteName); for (let testName of testNames[suiteName]) { - runTest(suiteName, testName); + await runTest(suiteName, testName); } } } -export function runTest(suiteName, testName) { - RealmTests.runTest(suiteName, 'beforeEach'); +export async function runTest(suiteName, testName) { + await RealmTests.runTest(suiteName, 'beforeEach'); try { - RealmTests.runTest(suiteName, testName); + await RealmTests.runTest(suiteName, testName); console.log('+ ' + testName); } catch (e) { @@ -75,6 +75,6 @@ export function runTest(suiteName, testName) { throw e; } finally { - RealmTests.runTest(suiteName, 'afterEach'); + await RealmTests.runTest(suiteName, 'afterEach'); } } From b42f5ab2858851154e758b95189a56e489b2bc5c Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Tue, 26 Apr 2016 00:10:21 -0700 Subject: [PATCH 20/21] Allow Node tests to be asynchronous --- tests/index.js | 55 ++++++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/tests/index.js b/tests/index.js index acc0576b..d7dc622b 100644 --- a/tests/index.js +++ b/tests/index.js @@ -50,28 +50,27 @@ function runTests() { } }; - for (let suiteName in testNames) { - console.log('Starting ' + suiteName); + return Object.keys(testNames).reduce((suitePromiseChain, suiteName) => { + return suitePromiseChain.then(() => { + console.log('Starting ' + suiteName); - for (let testName of testNames[suiteName]) { - RealmTests.runTest(suiteName, 'beforeEach'); - - try { - RealmTests.runTest(suiteName, testName); - console.log('+ ' + testName); - } - catch (e) { - console.warn('- ' + testName); - console.error(e.message, e.stack); - passed = false; - } - finally { - RealmTests.runTest(suiteName, 'afterEach'); - } - } - } - - return passed; + return testNames[suiteName].reduce((testPromiseChain, testName) => { + return testPromiseChain.then(() => { + return RealmTests.runTest(suiteName, 'beforeEach'); + }).then(() => { + return RealmTests.runTest(suiteName, testName); + }).then(() => { + console.log('+ ' + testName); + }, (err) => { + console.warn('- ' + testName); + console.warn(err.message || err); + passed = false; + }).then(() => { + return RealmTests.runTest(suiteName, 'afterEach'); + }); + }, Promise.resolve()); + }); + }, Promise.resolve()).then(() => passed); } if (require.main == module) { @@ -79,7 +78,15 @@ if (require.main == module) { mockery.warnOnUnregistered(false); mockery.registerMock('realm', require('..')); - if (!runTests()) { - process.exit(1); - } + runTests().then( + (passed) => { + if (!passed) { + process.exit(1); + } + }, + (err) => { + console.error(err); + process.exit(1); + } + ); } From 17e7153a59f101618cef4d69b6b7f1b132e3cb83 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Tue, 26 Apr 2016 02:04:13 -0700 Subject: [PATCH 21/21] Very basic multiprocess change notification test --- tests/index.js | 5 +++ tests/js/worker-tests-script.js | 56 ++++++++++++++++++++++++ tests/js/worker-tests.js | 76 +++++++++++++++++++++++++++++++++ tests/js/worker.js | 44 +++++++++++++++++++ 4 files changed, 181 insertions(+) create mode 100644 tests/js/worker-tests-script.js create mode 100644 tests/js/worker-tests.js create mode 100644 tests/js/worker.js diff --git a/tests/index.js b/tests/index.js index d7dc622b..e22b797a 100644 --- a/tests/index.js +++ b/tests/index.js @@ -28,6 +28,11 @@ const mockery = require('mockery'); function runTests() { const Realm = require('realm'); const RealmTests = require('./js'); + + RealmTests.registerTests({ + WorkerTests: require('./js/worker-tests'), + }); + const testNames = RealmTests.getTestNames(); let passed = true; diff --git a/tests/js/worker-tests-script.js b/tests/js/worker-tests-script.js new file mode 100644 index 00000000..ec16d13b --- /dev/null +++ b/tests/js/worker-tests-script.js @@ -0,0 +1,56 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2016 Realm Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////// + +/* eslint-env es6, node */ +/* eslint-disable no-console */ + +'use strict'; + +const Realm = require('../..'); + +const handlers = { + create(options) { + let realm = new Realm(options.config); + + realm.write(() => { + realm.create(options.type, options.properties); + }); + } +}; + +process.on('message', (message) => { + process.send(handleMessage(message)); +}); + +function handleMessage(message) { + let error, result; + + try { + let handler = handlers[message.action]; + if (handler) { + result = handler(message); + } else { + throw new Error('Unknown worker action: ' + message.action); + } + } catch (e) { + console.warn(e); + error = e.message; + } + + return {error, result}; +} diff --git a/tests/js/worker-tests.js b/tests/js/worker-tests.js new file mode 100644 index 00000000..d3bbba4f --- /dev/null +++ b/tests/js/worker-tests.js @@ -0,0 +1,76 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2016 Realm Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////// + +/* eslint-env es6, node */ + +'use strict'; + +const Realm = require('realm'); +const TestCase = require('./asserts'); +const schemas = require('./schemas'); +const Worker = require('./worker'); + +module.exports = { + testChangeNotifications() { + return new Promise((resolve, reject) => { + let config = {schema: [schemas.TestObject]}; + let realm = new Realm(config); + let objects = realm.objects('TestObject'); + let worker = new Worker(__dirname + '/worker-tests-script.js'); + + // Test will fail if it does not receive a change event within a second. + let timer = setTimeout(() => { + reject(new Error('Timed out waiting for change notification')); + }, 1000); + + let cleanup = () => { + clearTimeout(timer); + worker.terminate(); + }; + + // Test will pass if it receives a change event and the Realm changed. + realm.addListener('change', () => { + try { + TestCase.assertEqual(objects.length, 1); + TestCase.assertEqual(objects[0].doubleCol, 42); + resolve(); + } catch (e) { + reject(e); + } finally { + cleanup(); + } + }); + + worker.onmessage = (message) => { + if (message.error) { + cleanup(); + reject(message.error); + } + }; + + worker.postMessage({ + action: 'create', + config: config, + type: 'TestObject', + properties: { + doubleCol: 42, + } + }); + }); + } +}; diff --git a/tests/js/worker.js b/tests/js/worker.js new file mode 100644 index 00000000..86b1b6f0 --- /dev/null +++ b/tests/js/worker.js @@ -0,0 +1,44 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2016 Realm Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////// + +/* eslint-env es6, node */ + +'use strict'; + +class Worker { + constructor(script) { + this._process = require('child_process').fork(script); + + this._process.on('message', (message) => { + if (this.onmessage) { + this.onmessage(message); + } + }); + } + postMessage(message) { + this._process.send(message); + } + terminate() { + if (this._process) { + this._process.kill(); + delete this._process; + } + } +} + +module.exports = Worker;