diff --git a/CHANGELOG.md b/CHANGELOG.md index 42fd136d..7e949134 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,10 @@ 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 +* Fix for crash when setting object properties to objects from other Realms 0.13.2 Release notes (2016-5-26) ============================================================= 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. 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/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..b1555215 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.1.0", + "react-native": "^0.27.1", "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/.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/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..fffbe254 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.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/lib/browser/index.js b/lib/browser/index.js index f14f22ef..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,21 +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) { + let method = util.createMethod(objectTypes.REALM, 'objectForPrimaryKey'); + return method.apply(this, [getObjectType(this, type), ...args]); } } diff --git a/logo.png b/logo.png index cbe78177..c64d652d 100644 Binary files a/logo.png and b/logo.png differ 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 diff --git a/src/RealmJS.xcodeproj/project.pbxproj b/src/RealmJS.xcodeproj/project.pbxproj index c2726b19..5f16c042 100644 --- a/src/RealmJS.xcodeproj/project.pbxproj +++ b/src/RealmJS.xcodeproj/project.pbxproj @@ -19,7 +19,6 @@ 02D041F71CE11159000E4250 /* dates-v3.realm in Resources */ = {isa = PBXBuildFile; fileRef = 02D041F61CE11159000E4250 /* dates-v3.realm */; }; 02D8D1F71B601984006DB49D /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CCD1AE99D4D009B348C /* JavaScriptCore.framework */; }; 02E008D51D10ABB600F3AA37 /* format.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02E008D21D10AB1B00F3AA37 /* format.cpp */; }; - 02E008D61D10AC6B00F3AA37 /* format.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02E008D21D10AB1B00F3AA37 /* format.cpp */; }; 02F59EBF1C88F17D007F774C /* index_set.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EAF1C88F17D007F774C /* index_set.cpp */; }; 02F59EC01C88F17D007F774C /* list.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EB11C88F17D007F774C /* list.cpp */; }; 02F59EC11C88F17D007F774C /* object_schema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EB41C88F17D007F774C /* object_schema.cpp */; }; @@ -72,6 +71,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 */ @@ -766,16 +770,21 @@ buildActionMask = 2147483647; files = ( 02E008D61D10AC6B00F3AA37 /* format.cpp in Sources */, + 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 */, @@ -995,87 +1004,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 = { @@ -1107,35 +1035,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 = { @@ -1179,15 +1078,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 = { @@ -1212,16 +1102,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 = { @@ -1239,7 +1119,6 @@ isa = XCConfigurationList; buildConfigurations = ( 02B58CC51AE99CEC009B348C /* Debug */, - 02F9EE1C1B6BF66300C807E8 /* GCov_Build */, 02B58CC61AE99CEC009B348C /* Release */, ); defaultConfigurationIsVisible = 0; @@ -1249,7 +1128,6 @@ isa = XCConfigurationList; buildConfigurations = ( 02B58CCB1AE99CEC009B348C /* Debug */, - 02F9EE1E1B6BF66300C807E8 /* GCov_Build */, 02B58CCC1AE99CEC009B348C /* Release */, ); defaultConfigurationIsVisible = 0; @@ -1259,7 +1137,6 @@ isa = XCConfigurationList; buildConfigurations = ( F62BF8FC1CAC71780022BCDC /* Debug */, - F62BF8FD1CAC71780022BCDC /* GCov_Build */, F62BF8FE1CAC71780022BCDC /* Release */, ); defaultConfigurationIsVisible = 0; @@ -1269,7 +1146,6 @@ isa = XCConfigurationList; buildConfigurations = ( F63FF2B71C1241E500B3B8E0 /* Debug */, - F63FF2B81C1241E500B3B8E0 /* GCov_Build */, F63FF2B91C1241E500B3B8E0 /* Release */, ); defaultConfigurationIsVisible = 0; @@ -1279,7 +1155,6 @@ isa = XCConfigurationList; buildConfigurations = ( F63FF2F61C16405D00B3B8E0 /* Debug */, - F63FF2F71C16405D00B3B8E0 /* GCov_Build */, F63FF2F81C16405D00B3B8E0 /* Release */, ); defaultConfigurationIsVisible = 0; diff --git a/src/js_list.hpp b/src/js_list.hpp index d936159c..ad119f5b 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 @@ -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 8ee7d9a6..512de6ce 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); @@ -117,15 +120,21 @@ 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(); + 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, realm_object); + return RealmObjectClass::create_instance(ctx, std::move(realm_object)); } static size_t list_size(ContextType ctx, ValueType &value) { @@ -135,7 +144,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 ValueType from_results(ContextType ctx, realm::Results results) { return ResultsClass::create_instance(ctx, results); diff --git a/src/js_realm.hpp b/src/js_realm.hpp index a03736d1..ed0ce5e0 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}, @@ -206,20 +208,35 @@ public: return name; } - // 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 +479,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 +505,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,8 +517,8 @@ 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); - return_value.set(RealmObjectClass::create_instance(ctx, realm_object)); + auto realm_object = realm::Object::create(ctx, realm, object_schema, object, update); + 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 0751f419..c113c515 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..08991f46 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); @@ -126,7 +119,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)); @@ -208,7 +201,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 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/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; 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(); 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 4f12afe7..4df51508 100644 --- a/src/object-store/src/object_accessor.hpp +++ b/src/object-store/src/object_accessor.hpp @@ -48,6 +48,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; } @@ -63,6 +66,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(); }; @@ -104,7 +110,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 accessors static size_t list_size(ContextType ctx, ValueType &val); @@ -143,6 +149,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 ReadOnlyPropertyValueException : public std::runtime_error { public: ReadOnlyPropertyValueException(const std::string& object_type, const std::string& property_name, const std::string& message) @@ -326,20 +339,15 @@ 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, - "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."); } } @@ -373,7 +381,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/src/object-store/src/parser/query_builder.hpp b/src/object-store/src/parser/query_builder.hpp index 169f53e0..5f773d77 100644 --- a/src/object-store/src/parser/query_builder.hpp +++ b/src/object-store/src/parser/query_builder.hpp @@ -48,7 +48,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)); } @@ -58,12 +59,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) { return m_arguments.at(index); diff --git a/tests/index.js b/tests/index.js index acc0576b..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; @@ -50,28 +55,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 +83,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); + } + ); } 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/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]}); diff --git a/tests/js/realm-tests.js b/tests/js/realm-tests.js index 628adfde..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() { @@ -273,7 +278,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 +365,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); }); }, @@ -638,6 +656,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/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); }); }, 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', 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; 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/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/package.json b/tests/react-test-app/package.json index be90074d..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": "^0.14.8", - "react-native": "^0.25.1", + "react": "15.1.0", + "react-native": "^0.27.1", "react-native-fs": "^1.1.0", "xmlbuilder": "^4.2.1", "realm": "file:../..", 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'); } }