merge latest master

This commit is contained in:
Ari Lazier 2016-06-14 16:40:57 -07:00
commit 2e3b95f2e7
40 changed files with 644 additions and 314 deletions

View File

@ -5,9 +5,10 @@ x.x.x Release notes (yyyy-MM-dd)
### Enhancements ### Enhancements
* Added `isValid()` method to `List` and `Results` to check for deleleted or invalidated objects * Added `isValid()` method to `List` and `Results` to check for deleleted or invalidated objects
* Added `objectForPrimaryKey(type, key)` method to `Realm`
### Bugfixes ### Bugfixes
* None * Fix for crash when setting object properties to objects from other Realms
0.13.2 Release notes (2016-5-26) 0.13.2 Release notes (2016-5-26)
============================================================= =============================================================

View File

@ -106,6 +106,16 @@ class Realm {
*/ */
objects(type) {} 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`. * Add a listener `callback` for the specified event `name`.
* @param {string} name - The name of event that should cause the callback to be called. * @param {string} name - The name of event that should cause the callback to be called.

View File

@ -15,11 +15,6 @@
# Ignore react and fbjs where there are overlaps, but don't ignore # Ignore react and fbjs where there are overlaps, but don't ignore
# anything that react-native relies on # anything that react-native relies on
.*/node_modules/fbjs/lib/Map.js .*/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 .*/node_modules/fbjs/lib/ErrorUtils.js
# Flow has a built-in definition for the 'react' module which we prefer to use # 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/React.js
.*/node_modules/react/lib/ReactDOM.js .*/node_modules/react/lib/ReactDOM.js
.*/__mocks__/.*
.*/__tests__/.*
.*/commoner/test/source/widget/share.js
# Ignore commoner tests # Ignore commoner tests
.*/node_modules/commoner/test/.* .*/node_modules/commoner/test/.*
@ -40,26 +40,58 @@
# Ignore Website # Ignore Website
.*/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] [include]
[libs] [libs]
node_modules/react-native/Libraries/react-native/react-native-interface.js node_modules/react-native/Libraries/react-native/react-native-interface.js
node_modules/react-native/flow
flow/
[options] [options]
module.system=haste module.system=haste
esproposal.class_static_fields=enable
esproposal.class_instance_fields=enable
munge_underscores=true munge_underscores=true
module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub' 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=$FlowIssue
suppress_type=$FlowFixMe suppress_type=$FlowFixMe
suppress_type=$FixMe 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\\)*\\$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-1]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ 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 suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
[version] [version]
0.21.0 ^0.25.0

View File

@ -51,9 +51,9 @@
-keepattributes Signature -keepattributes Signature
-keepattributes *Annotation* -keepattributes *Annotation*
-keep class com.squareup.okhttp.** { *; } -keep class okhttp3.** { *; }
-keep interface com.squareup.okhttp.** { *; } -keep interface okhttp3.** { *; }
-dontwarn com.squareup.okhttp.** -dontwarn okhttp3.**
# okio # okio
@ -61,7 +61,3 @@
-dontwarn java.nio.file.* -dontwarn java.nio.file.*
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
-dontwarn okio.** -dontwarn okio.**
# stetho
-dontwarn com.facebook.stetho.**

View File

@ -21,7 +21,6 @@
import React from 'react'; import React from 'react';
import { import {
Component,
Navigator, Navigator,
Platform, Platform,
StatusBar, StatusBar,
@ -35,7 +34,7 @@ import TodoListView from './todo-listview';
import realm from './realm'; import realm from './realm';
import styles from './styles'; import styles from './styles';
export default class TodoApp extends Component { export default class TodoApp extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);

View File

@ -6,8 +6,8 @@
"start": "react-native start" "start": "react-native start"
}, },
"dependencies": { "dependencies": {
"react": "^0.14.8", "react": "15.1.0",
"react-native": "^0.25.1", "react-native": "^0.27.1",
"realm": "file:../.." "realm": "file:../.."
} }
} }

View File

@ -18,11 +18,11 @@
'use strict'; 'use strict';
import React from 'react-native'; import React from 'react';
const rootComponentPromise = new Promise((resolve) => { const rootComponentPromise = new Promise((resolve) => {
// Require internal module here so the promise is rejected if there is an error. // 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; let renderComponent = Mount.renderComponent;
Mount.renderComponent = function() { Mount.renderComponent = function() {

View File

@ -15,11 +15,6 @@
# Ignore react and fbjs where there are overlaps, but don't ignore # Ignore react and fbjs where there are overlaps, but don't ignore
# anything that react-native relies on # anything that react-native relies on
.*/node_modules/fbjs/lib/Map.js .*/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 .*/node_modules/fbjs/lib/ErrorUtils.js
# Flow has a built-in definition for the 'react' module which we prefer to use # 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/React.js
.*/node_modules/react/lib/ReactDOM.js .*/node_modules/react/lib/ReactDOM.js
.*/__mocks__/.*
.*/__tests__/.*
.*/commoner/test/source/widget/share.js
# Ignore commoner tests # Ignore commoner tests
.*/node_modules/commoner/test/.* .*/node_modules/commoner/test/.*
@ -40,26 +40,58 @@
# Ignore Website # Ignore Website
.*/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] [include]
[libs] [libs]
node_modules/react-native/Libraries/react-native/react-native-interface.js node_modules/react-native/Libraries/react-native/react-native-interface.js
node_modules/react-native/flow
flow/
[options] [options]
module.system=haste module.system=haste
esproposal.class_static_fields=enable
esproposal.class_instance_fields=enable
munge_underscores=true munge_underscores=true
module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub' 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=$FlowIssue
suppress_type=$FlowFixMe suppress_type=$FlowFixMe
suppress_type=$FixMe 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\\)*\\$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-1]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ 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 suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
[version] [version]
0.21.0 ^0.25.0

View File

@ -51,9 +51,9 @@
-keepattributes Signature -keepattributes Signature
-keepattributes *Annotation* -keepattributes *Annotation*
-keep class com.squareup.okhttp.** { *; } -keep class okhttp3.** { *; }
-keep interface com.squareup.okhttp.** { *; } -keep interface okhttp3.** { *; }
-dontwarn com.squareup.okhttp.** -dontwarn okhttp3.**
# okio # okio
@ -61,7 +61,3 @@
-dontwarn java.nio.file.* -dontwarn java.nio.file.*
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
-dontwarn okio.** -dontwarn okio.**
# stetho
-dontwarn com.facebook.stetho.**

View File

@ -21,7 +21,6 @@
import React from 'react'; import React from 'react';
import { import {
Component,
StyleSheet, StyleSheet,
Text, Text,
View, View,
@ -355,7 +354,7 @@ class RNSqliteTests extends Tests {
const apiTests = [new RealmTests, new RNSqliteTests, new RNStoreTests]; const apiTests = [new RealmTests, new RNSqliteTests, new RNStoreTests];
export default class ReactNativeBenchmarks extends Component { export default class ReactNativeBenchmarks extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);

View File

@ -6,8 +6,8 @@
"start": "react-native start" "start": "react-native start"
}, },
"dependencies": { "dependencies": {
"react": "^0.14.8", "react": "15.1.0",
"react-native": "^0.25.1", "react-native": "^0.27.1",
"react-native-sqlite-storage": "^2.1.3", "react-native-sqlite-storage": "^2.1.3",
"react-native-store": "^0.4.1", "react-native-store": "^0.4.1",
"realm": "file:../.." "realm": "file:../.."

View File

@ -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 { export default class Realm {
constructor(config) { constructor(config) {
let schemas = typeof config == 'object' && config.schema; let schemas = typeof config == 'object' && config.schema;
@ -90,21 +97,18 @@ export default class Realm {
} }
create(type, ...args) { create(type, ...args) {
if (typeof type == 'function') {
type = objects.typeForConstructor(this[keys.realm], type);
}
let method = util.createMethod(objectTypes.REALM, 'create', true); 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) { objects(type, ...args) {
if (typeof type == 'function') { let method = util.createMethod(objectTypes.REALM, 'objects');
type = objects.typeForConstructor(this[keys.realm], type); return method.apply(this, [getObjectType(this, type), ...args]);
} }
let method = util.createMethod(objectTypes.REALM, 'objects'); objectForPrimaryKey(type, ...args) {
return method.apply(this, [type, ...args]); let method = util.createMethod(objectTypes.REALM, 'objectForPrimaryKey');
return method.apply(this, [getObjectType(this, type), ...args]);
} }
} }

BIN
logo.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@ -37,7 +37,8 @@ LOCAL_SRC_FILES := \
src/object-store/src/impl/realm_coordinator.cpp \ src/object-store/src/impl/realm_coordinator.cpp \
src/object-store/src/impl/results_notifier.cpp \ src/object-store/src/impl/results_notifier.cpp \
src/object-store/src/impl/transact_log_handler.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 vendor/base64.cpp
LOCAL_C_INCLUDES := src LOCAL_C_INCLUDES := src

View File

@ -19,7 +19,6 @@
02D041F71CE11159000E4250 /* dates-v3.realm in Resources */ = {isa = PBXBuildFile; fileRef = 02D041F61CE11159000E4250 /* dates-v3.realm */; }; 02D041F71CE11159000E4250 /* dates-v3.realm in Resources */ = {isa = PBXBuildFile; fileRef = 02D041F61CE11159000E4250 /* dates-v3.realm */; };
02D8D1F71B601984006DB49D /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CCD1AE99D4D009B348C /* JavaScriptCore.framework */; }; 02D8D1F71B601984006DB49D /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CCD1AE99D4D009B348C /* JavaScriptCore.framework */; };
02E008D51D10ABB600F3AA37 /* format.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02E008D21D10AB1B00F3AA37 /* format.cpp */; }; 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 */; }; 02F59EBF1C88F17D007F774C /* index_set.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EAF1C88F17D007F774C /* index_set.cpp */; };
02F59EC01C88F17D007F774C /* list.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EB11C88F17D007F774C /* list.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 */; }; 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 */; }; F674784A1CC81F1900F9273C /* platform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F67478481CC81F1300F9273C /* platform.cpp */; };
F68A278C1BC2722A0063D40A /* RJSModuleLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = F68A278B1BC2722A0063D40A /* RJSModuleLoader.m */; }; F68A278C1BC2722A0063D40A /* RJSModuleLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = F68A278B1BC2722A0063D40A /* RJSModuleLoader.m */; };
F6BCCFE21C8380A400FE31AE /* lib in Resources */ = {isa = PBXBuildFile; fileRef = F6BCCFDF1C83809A00FE31AE /* lib */; }; 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 */ /* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */ /* Begin PBXCopyFilesBuildPhase section */
@ -766,16 +770,21 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
02E008D61D10AC6B00F3AA37 /* format.cpp in Sources */, 02E008D61D10AC6B00F3AA37 /* format.cpp in Sources */,
F6E931BA1CFEAE170016AF14 /* collection_notifications.cpp in Sources */,
F60102D31CBB966E00EC01BA /* js_realm.cpp in Sources */, F60102D31CBB966E00EC01BA /* js_realm.cpp in Sources */,
F60102D61CBB96B400EC01BA /* object_schema.cpp in Sources */, F60102D61CBB96B400EC01BA /* object_schema.cpp in Sources */,
F60102D41CBB96AB00EC01BA /* index_set.cpp in Sources */, F60102D41CBB96AB00EC01BA /* index_set.cpp in Sources */,
F60102DB1CBB96C600EC01BA /* parser.cpp in Sources */, F60102DB1CBB96C600EC01BA /* parser.cpp in Sources */,
F6E931BB1CFEAE310016AF14 /* collection_change_builder.cpp in Sources */,
F60102D51CBB96AE00EC01BA /* list.cpp in Sources */, F60102D51CBB96AE00EC01BA /* list.cpp in Sources */,
F6E931BC1CFEAE340016AF14 /* collection_notifier.cpp in Sources */,
F60102DC1CBB96C900EC01BA /* query_builder.cpp in Sources */, F60102DC1CBB96C900EC01BA /* query_builder.cpp in Sources */,
F60102DD1CBB96CC00EC01BA /* external_commit_helper.cpp in Sources */, F60102DD1CBB96CC00EC01BA /* external_commit_helper.cpp in Sources */,
F63117F01CEB0D5F00ECB2DE /* weak_realm_notifier.cpp in Sources */, F63117F01CEB0D5F00ECB2DE /* weak_realm_notifier.cpp in Sources */,
F60102E11CBB96DD00EC01BA /* transact_log_handler.cpp in Sources */, F60102E11CBB96DD00EC01BA /* transact_log_handler.cpp in Sources */,
F6E931BE1CFEAE3A0016AF14 /* results_notifier.cpp in Sources */,
F60102D71CBB96B800EC01BA /* object_store.cpp in Sources */, F60102D71CBB96B800EC01BA /* object_store.cpp in Sources */,
F6E931BD1CFEAE370016AF14 /* list_notifier.cpp in Sources */,
F60102DA1CBB96C300EC01BA /* shared_realm.cpp in Sources */, F60102DA1CBB96C300EC01BA /* shared_realm.cpp in Sources */,
F60102E01CBB96D900EC01BA /* realm_coordinator.cpp in Sources */, F60102E01CBB96D900EC01BA /* realm_coordinator.cpp in Sources */,
F60102EA1CBCAFC300EC01BA /* node_dummy.cpp in Sources */, F60102EA1CBCAFC300EC01BA /* node_dummy.cpp in Sources */,
@ -995,87 +1004,6 @@
}; };
name = Release; 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 */ = { F62BF8FC1CAC71780022BCDC /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
@ -1107,35 +1035,6 @@
}; };
name = Debug; 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 */ = { F62BF8FE1CAC71780022BCDC /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
@ -1179,15 +1078,6 @@
}; };
name = Debug; 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 */ = { F63FF2B91C1241E500B3B8E0 /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
@ -1212,16 +1102,6 @@
}; };
name = Debug; 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 */ = { F63FF2F81C16405D00B3B8E0 /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
@ -1239,7 +1119,6 @@
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (
02B58CC51AE99CEC009B348C /* Debug */, 02B58CC51AE99CEC009B348C /* Debug */,
02F9EE1C1B6BF66300C807E8 /* GCov_Build */,
02B58CC61AE99CEC009B348C /* Release */, 02B58CC61AE99CEC009B348C /* Release */,
); );
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;
@ -1249,7 +1128,6 @@
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (
02B58CCB1AE99CEC009B348C /* Debug */, 02B58CCB1AE99CEC009B348C /* Debug */,
02F9EE1E1B6BF66300C807E8 /* GCov_Build */,
02B58CCC1AE99CEC009B348C /* Release */, 02B58CCC1AE99CEC009B348C /* Release */,
); );
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;
@ -1259,7 +1137,6 @@
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (
F62BF8FC1CAC71780022BCDC /* Debug */, F62BF8FC1CAC71780022BCDC /* Debug */,
F62BF8FD1CAC71780022BCDC /* GCov_Build */,
F62BF8FE1CAC71780022BCDC /* Release */, F62BF8FE1CAC71780022BCDC /* Release */,
); );
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;
@ -1269,7 +1146,6 @@
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (
F63FF2B71C1241E500B3B8E0 /* Debug */, F63FF2B71C1241E500B3B8E0 /* Debug */,
F63FF2B81C1241E500B3B8E0 /* GCov_Build */,
F63FF2B91C1241E500B3B8E0 /* Release */, F63FF2B91C1241E500B3B8E0 /* Release */,
); );
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;
@ -1279,7 +1155,6 @@
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (
F63FF2F61C16405D00B3B8E0 /* Debug */, F63FF2F61C16405D00B3B8E0 /* Debug */,
F63FF2F71C16405D00B3B8E0 /* GCov_Build */,
F63FF2F81C16405D00B3B8E0 /* Release */, F63FF2F81C16405D00B3B8E0 /* Release */,
); );
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;

View File

@ -41,7 +41,7 @@ struct ListClass : ClassDefinition<T, realm::List, CollectionClass<T>> {
using Value = js::Value<T>; using Value = js::Value<T>;
using ReturnValue = js::ReturnValue<T>; using ReturnValue = js::ReturnValue<T>;
static ObjectType create_instance(ContextType, realm::List &); static ObjectType create_instance(ContextType, realm::List);
// properties // properties
static void get_length(ContextType, ObjectType, ReturnValue &); static void get_length(ContextType, ObjectType, ReturnValue &);
@ -81,8 +81,8 @@ struct ListClass : ClassDefinition<T, realm::List, CollectionClass<T>> {
}; };
template<typename T> template<typename T>
typename T::Object ListClass<T>::create_instance(ContextType ctx, realm::List &list) { typename T::Object ListClass<T>::create_instance(ContextType ctx, realm::List list) {
return create_object<T, ListClass<T>>(ctx, new realm::List(list)); return create_object<T, ListClass<T>>(ctx, new realm::List(std::move(list)));
} }
template<typename T> template<typename T>
@ -96,7 +96,7 @@ void ListClass<T>::get_index(ContextType ctx, ObjectType object, uint32_t index,
auto list = get_internal<T, ListClass<T>>(object); auto list = get_internal<T, ListClass<T>>(object);
auto realm_object = realm::Object(list->get_realm(), list->get_object_schema(), list->get(index)); auto realm_object = realm::Object(list->get_realm(), list->get_object_schema(), list->get(index));
return_value.set(RealmObjectClass<T>::create_instance(ctx, realm_object)); return_value.set(RealmObjectClass<T>::create_instance(ctx, std::move(realm_object)));
} }
template<typename T> template<typename T>
@ -132,7 +132,7 @@ void ListClass<T>::pop(ContextType ctx, ObjectType this_object, size_t argc, con
size_t index = size - 1; size_t index = size - 1;
auto realm_object = realm::Object(list->get_realm(), list->get_object_schema(), list->get(index)); auto realm_object = realm::Object(list->get_realm(), list->get_object_schema(), list->get(index));
return_value.set(RealmObjectClass<T>::create_instance(ctx, realm_object)); return_value.set(RealmObjectClass<T>::create_instance(ctx, std::move(realm_object)));
list->remove(index); list->remove(index);
} }
} }
@ -161,7 +161,7 @@ void ListClass<T>::shift(ContextType ctx, ObjectType this_object, size_t argc, c
else { else {
auto realm_object = realm::Object(list->get_realm(), list->get_object_schema(), list->get(0)); auto realm_object = realm::Object(list->get_realm(), list->get_object_schema(), list->get(0));
return_value.set(RealmObjectClass<T>::create_instance(ctx, realm_object)); return_value.set(RealmObjectClass<T>::create_instance(ctx, std::move(realm_object)));
list->remove(0); list->remove(0);
} }
} }
@ -192,7 +192,7 @@ void ListClass<T>::splice(ContextType ctx, ObjectType this_object, size_t argc,
for (size_t i = 0; i < remove; i++) { for (size_t i = 0; i < remove; i++) {
auto realm_object = realm::Object(list->get_realm(), list->get_object_schema(), list->get(index)); auto realm_object = realm::Object(list->get_realm(), list->get_object_schema(), list->get(index));
removed_objects.push_back(RealmObjectClass<T>::create_instance(ctx, realm_object)); removed_objects.push_back(RealmObjectClass<T>::create_instance(ctx, std::move(realm_object)));
list->remove(index); list->remove(index);
} }
for (size_t i = 2; i < argc; i++) { for (size_t i = 2; i < argc; i++) {

View File

@ -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) { 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); ObjectType object = Value::validated_to_object(ctx, value);
if (Object::template is_instance<RealmObjectClass<T>>(ctx, object)) { if (Object::template is_instance<RealmObjectClass<T>>(ctx, object)) {
return get_internal<T, RealmObjectClass<T>>(object)->row().get_index(); auto realm_object = get_internal<T, RealmObjectClass<T>>(object);
if (realm_object->realm() == realm) {
return realm_object->row().get_index();
}
} }
auto object_schema = realm->config().schema->find(type); auto object_schema = realm->config().schema->find(type);
@ -117,15 +120,21 @@ struct NativeAccessor {
auto child = realm::Object::create<ValueType>(ctx, realm, *object_schema, static_cast<ValueType>(object), try_update); auto child = realm::Object::create<ValueType>(ctx, realm, *object_schema, static_cast<ValueType>(object), try_update);
return child.row().get_index(); 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); ObjectType object = Value::validated_to_object(ctx, value);
if (Object::template is_instance<RealmObjectClass<T>>(ctx, object)) { if (!Object::template is_instance<RealmObjectClass<T>>(ctx, object)) {
return get_internal<T, RealmObjectClass<T>>(object)->row().get_index();
}
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<T, RealmObjectClass<T>>(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) { static ValueType from_object(ContextType ctx, realm::Object realm_object) {
return RealmObjectClass<T>::create_instance(ctx, realm_object); return RealmObjectClass<T>::create_instance(ctx, std::move(realm_object));
} }
static size_t list_size(ContextType ctx, ValueType &value) { 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); return Object::validated_get_object(ctx, Value::validated_to_object(ctx, value), (uint32_t)index);
} }
static ValueType from_list(ContextType ctx, realm::List list) { static ValueType from_list(ContextType ctx, realm::List list) {
return ListClass<T>::create_instance(ctx, list); return ListClass<T>::create_instance(ctx, std::move(list));
} }
static ValueType from_results(ContextType ctx, realm::Results results) { static ValueType from_results(ContextType ctx, realm::Results results) {
return ResultsClass<T>::create_instance(ctx, results); return ResultsClass<T>::create_instance(ctx, results);

View File

@ -141,6 +141,7 @@ public:
// methods // methods
static void objects(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &); 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 create(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &);
static void delete_one(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 &); static void delete_all(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &);
@ -180,6 +181,7 @@ public:
MethodMap<T> const methods = { MethodMap<T> const methods = {
{"objects", wrap<objects>}, {"objects", wrap<objects>},
{"objectForPrimaryKey", wrap<object_for_primary_key>},
{"create", wrap<create>}, {"create", wrap<create>},
{"delete", wrap<delete_one>}, {"delete", wrap<delete_one>},
{"deleteAll", wrap<delete_all>}, {"deleteAll", wrap<delete_all>},
@ -206,20 +208,35 @@ public:
return name; 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) {
static std::string validated_object_type_for_value(SharedRealm &realm, ContextType ctx, const ValueType &value) { std::string object_type;
if (Value::is_constructor(ctx, value)) { if (Value::is_constructor(ctx, value)) {
FunctionType constructor = Value::to_constructor(ctx, value); FunctionType constructor = Value::to_constructor(ctx, value);
auto delegate = get_delegate<T>(realm.get()); auto delegate = get_delegate<T>(realm.get());
for (auto &pair : delegate->m_constructors) { for (auto &pair : delegate->m_constructors) {
if (FunctionType(pair.second) == constructor) { if (FunctionType(pair.second) == constructor) {
return pair.first; object_type = pair.first;
break;
} }
} }
if (object_type.empty()) {
throw std::runtime_error("Constructor was not registered in the schema for this Realm"); 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) { static std::string normalize_path(std::string path) {
@ -462,9 +479,25 @@ void RealmClass<T>::objects(ContextType ctx, ObjectType this_object, size_t argc
validate_argument_count(argc, 1); validate_argument_count(argc, 1);
SharedRealm realm = *get_internal<T, RealmClass<T>>(this_object); SharedRealm realm = *get_internal<T, RealmClass<T>>(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<T>::create_instance(ctx, realm, type)); return_value.set(ResultsClass<T>::create_instance(ctx, realm, object_schema));
}
template<typename T>
void RealmClass<T>::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<T, RealmClass<T>>(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<T>::create_instance(ctx, std::move(realm_object)));
}
else {
return_value.set_undefined();
}
} }
template<typename T> template<typename T>
@ -472,17 +505,11 @@ void RealmClass<T>::create(ContextType ctx, ObjectType this_object, size_t argc,
validate_argument_count(argc, 2, 3); validate_argument_count(argc, 2, 3);
SharedRealm realm = *get_internal<T, RealmClass<T>>(this_object); SharedRealm realm = *get_internal<T, RealmClass<T>>(this_object);
std::string className = validated_object_type_for_value(realm, ctx, arguments[0]); auto &object_schema = validated_object_schema_for_value(ctx, realm, 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.");
}
ObjectType object = Value::validated_to_object(ctx, arguments[1], "properties"); ObjectType object = Value::validated_to_object(ctx, arguments[1], "properties");
if (Value::is_array(ctx, arguments[1])) { if (Value::is_array(ctx, arguments[1])) {
object = Schema<T>::dict_for_property_array(ctx, *object_schema, object); object = Schema<T>::dict_for_property_array(ctx, object_schema, object);
} }
bool update = false; bool update = false;
@ -490,8 +517,8 @@ void RealmClass<T>::create(ContextType ctx, ObjectType this_object, size_t argc,
update = Value::validated_to_boolean(ctx, arguments[2], "update"); update = Value::validated_to_boolean(ctx, arguments[2], "update");
} }
auto realm_object = realm::Object::create<ValueType>(ctx, realm, *object_schema, object, update); auto realm_object = realm::Object::create<ValueType>(ctx, realm, object_schema, object, update);
return_value.set(RealmObjectClass<T>::create_instance(ctx, realm_object)); return_value.set(RealmObjectClass<T>::create_instance(ctx, std::move(realm_object)));
} }
template<typename T> template<typename T>

View File

@ -40,7 +40,7 @@ struct RealmObjectClass : ClassDefinition<T, realm::Object> {
using Function = js::Function<T>; using Function = js::Function<T>;
using ReturnValue = js::ReturnValue<T>; using ReturnValue = js::ReturnValue<T>;
static ObjectType create_instance(ContextType, realm::Object &); static ObjectType create_instance(ContextType, realm::Object);
static void get_property(ContextType, ObjectType, const String &, ReturnValue &); static void get_property(ContextType, ObjectType, const String &, ReturnValue &);
static bool set_property(ContextType, ObjectType, const String &, ValueType); static bool set_property(ContextType, ObjectType, const String &, ValueType);
@ -67,12 +67,12 @@ void RealmObjectClass<T>::is_valid(ContextType ctx, ObjectType this_object, size
} }
template<typename T> template<typename T>
typename T::Object RealmObjectClass<T>::create_instance(ContextType ctx, realm::Object &realm_object) { typename T::Object RealmObjectClass<T>::create_instance(ContextType ctx, realm::Object realm_object) {
static String prototype_string = "prototype"; static String prototype_string = "prototype";
auto delegate = get_delegate<T>(realm_object.realm().get()); auto delegate = get_delegate<T>(realm_object.realm().get());
auto name = realm_object.get_object_schema().name; auto name = realm_object.get_object_schema().name;
auto object = create_object<T, RealmObjectClass<T>>(ctx, new realm::Object(realm_object)); auto object = create_object<T, RealmObjectClass<T>>(ctx, new realm::Object(std::move(realm_object)));
if (!delegate || !delegate->m_constructors.count(name)) { if (!delegate || !delegate->m_constructors.count(name)) {
return object; return object;

View File

@ -40,7 +40,7 @@ struct ResultsClass : ClassDefinition<T, realm::Results, CollectionClass<T>> {
static ObjectType create_instance(ContextType, const realm::Results &, bool live = true); 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, 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); static ObjectType create_instance(ContextType, SharedRealm, const ObjectSchema &, Query, bool live = true);
template<typename U> template<typename U>
@ -87,16 +87,9 @@ typename T::Object ResultsClass<T>::create_instance(ContextType ctx, const realm
} }
template<typename T> template<typename T>
typename T::Object ResultsClass<T>::create_instance(ContextType ctx, SharedRealm realm, const std::string &type, bool live) { typename T::Object ResultsClass<T>::create_instance(ContextType ctx, SharedRealm realm, const ObjectSchema &object_schema, bool live) {
auto table = ObjectStore::table_for_object_type(realm->read_group(), type); auto table = ObjectStore::table_for_object_type(realm->read_group(), object_schema.name);
auto &schema = realm->config().schema; auto results = new realm::Results(realm, object_schema, *table);
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);
results->set_live(live); results->set_live(live);
return create_object<T, ResultsClass<T>>(ctx, results); return create_object<T, ResultsClass<T>>(ctx, results);
@ -126,7 +119,7 @@ typename T::Object ResultsClass<T>::create_filtered(ContextType ctx, const U &co
} }
parser::Predicate predicate = parser::parse(query_string); parser::Predicate predicate = parser::parse(query_string);
query_builder::ArgumentConverter<ValueType, ContextType> converter(ctx, args); query_builder::ArgumentConverter<ValueType, ContextType> converter(ctx, realm, args);
query_builder::apply_predicate(query, predicate, converter, *realm->config().schema, object_schema.name); query_builder::apply_predicate(query, predicate, converter, *realm->config().schema, object_schema.name);
return create_instance(ctx, realm, object_schema, std::move(query)); return create_instance(ctx, realm, object_schema, std::move(query));
@ -208,7 +201,7 @@ void ResultsClass<T>::get_index(ContextType ctx, ObjectType object, uint32_t ind
} }
auto realm_object = realm::Object(results->get_realm(), results->get_object_schema(), results->get(index)); auto realm_object = realm::Object(results->get_realm(), results->get_object_schema(), results->get(index));
return_value.set(RealmObjectClass<T>::create_instance(ctx, realm_object)); return_value.set(RealmObjectClass<T>::create_instance(ctx, std::move(realm_object)));
} }
template<typename T> template<typename T>

View File

@ -169,7 +169,7 @@ inline JSClassRef ObjectWrap<ClassType>::create_constructor_class() {
// This must be set for `typeof constructor` to be 'function'. // This must be set for `typeof constructor` to be 'function'.
definition.callAsFunction = call; definition.callAsFunction = call;
if (s_class.constructor) { if (reinterpret_cast<void*>(s_class.constructor)) {
definition.callAsConstructor = construct; definition.callAsConstructor = construct;
} }
if (!s_class.static_methods.empty()) { if (!s_class.static_methods.empty()) {
@ -226,7 +226,7 @@ inline JSValueRef ObjectWrap<ClassType>::call(JSContextRef ctx, JSObjectRef func
} }
// Classes without a constructor should still be subclassable. // Classes without a constructor should still be subclassable.
if (s_class.constructor) { if (reinterpret_cast<void*>(s_class.constructor)) {
try { try {
s_class.constructor(ctx, this_object, argc, arguments); s_class.constructor(ctx, this_object, argc, arguments);
} }
@ -241,7 +241,7 @@ inline JSValueRef ObjectWrap<ClassType>::call(JSContextRef ctx, JSObjectRef func
template<typename ClassType> template<typename ClassType>
inline JSObjectRef ObjectWrap<ClassType>::construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef arguments[], JSValueRef* exception) { inline JSObjectRef ObjectWrap<ClassType>::construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef arguments[], JSValueRef* exception) {
if (!s_class.constructor) { if (!reinterpret_cast<void*>(s_class.constructor)) {
*exception = jsc::Exception::value(ctx, s_class.name + " is not a constructor"); *exception = jsc::Exception::value(ctx, s_class.name + " is not a constructor");
return nullptr; return nullptr;
} }

View File

@ -30,7 +30,6 @@ namespace jsc {
struct Types { struct Types {
using Context = JSContextRef; using Context = JSContextRef;
using GlobalContext = JSGlobalContextRef; using GlobalContext = JSGlobalContextRef;
using ClassDefinition = JSClassRef;
using Value = JSValueRef; using Value = JSValueRef;
using Object = JSObjectRef; using Object = JSObjectRef;
using String = JSStringRef; using String = JSStringRef;

View File

@ -226,7 +226,7 @@ inline void ObjectWrap<ClassType>::construct(Nan::NAN_METHOD_ARGS_TYPE info) {
if (!info.IsConstructCall()) { if (!info.IsConstructCall()) {
Nan::ThrowError("Constructor must be called with new"); Nan::ThrowError("Constructor must be called with new");
} }
if (s_class.constructor) { if (reinterpret_cast<void*>(s_class.constructor)) {
auto isolate = info.GetIsolate(); auto isolate = info.GetIsolate();
auto arguments = get_arguments(info); auto arguments = get_arguments(info);
v8::Local<v8::Object> this_object = info.This(); v8::Local<v8::Object> this_object = info.This();

View File

@ -80,7 +80,7 @@ public:
struct ObserverState; 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. // external changes to a specific set of objects.
// This is called before each operation which may advance the read // This is called before each operation which may advance the read
// transaction to include // transaction to include

View File

@ -48,6 +48,9 @@ namespace realm {
template<typename ValueType, typename ContextType> template<typename ValueType, typename ContextType>
static inline Object create(ContextType ctx, SharedRealm realm, const ObjectSchema &object_schema, ValueType value, bool try_update); static inline Object create(ContextType ctx, SharedRealm realm, const ObjectSchema &object_schema, ValueType value, bool try_update);
template<typename ValueType, typename ContextType>
static Object get_for_primary_key(ContextType ctx, SharedRealm realm, const ObjectSchema &object_schema, ValueType primary_value);
SharedRealm realm() { return m_realm; } SharedRealm realm() { return m_realm; }
const ObjectSchema &get_object_schema() { return *m_object_schema; } const ObjectSchema &get_object_schema() { return *m_object_schema; }
Row row() { return m_row; } Row row() { return m_row; }
@ -64,6 +67,9 @@ namespace realm {
template<typename ValueType, typename ContextType> template<typename ValueType, typename ContextType>
inline ValueType get_property_value_impl(ContextType ctx, const Property &property); inline ValueType get_property_value_impl(ContextType ctx, const Property &property);
template<typename ValueType, typename ContextType>
static size_t get_for_primary_key_impl(ContextType ctx, const ConstTableRef &table, const Property &primary_prop, ValueType primary_value);
inline void verify_attached(); inline void verify_attached();
}; };
@ -104,7 +110,7 @@ namespace realm {
static ValueType from_object(ContextType ctx, Object); static ValueType from_object(ContextType ctx, Object);
// object index for an existing 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 // list value accessors
static size_t list_size(ContextType ctx, ValueType &val); static size_t list_size(ContextType ctx, ValueType &val);
@ -143,6 +149,13 @@ namespace realm {
const std::string property_name; 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 { class ReadOnlyPropertyValueException : public std::runtime_error {
public: public:
ReadOnlyPropertyValueException(const std::string& object_type, const std::string& property_name, const std::string& message) 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; size_t row_index = realm::not_found;
realm::TableRef table = ObjectStore::table_for_object_type(realm->read_group(), object_schema.name); realm::TableRef table = ObjectStore::table_for_object_type(realm->read_group(), object_schema.name);
const Property *primary_prop = object_schema.primary_key_property(); const Property *primary_prop = object_schema.primary_key_property();
if (primary_prop) { if (primary_prop) {
// search for existing object based on primary key type // search for existing object based on primary key type
ValueType primary_value = Accessor::dict_value_for_key(ctx, value, object_schema.primary_key); ValueType primary_value = Accessor::dict_value_for_key(ctx, value, object_schema.primary_key);
if (primary_prop->type == PropertyType::String) { row_index = get_for_primary_key_impl(ctx, table, *primary_prop, primary_value);
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));
}
if (!try_update && row_index != realm::not_found) { if (!try_update && row_index != realm::not_found) {
throw DuplicatePrimaryKeyValueException(object_schema.name, *primary_prop, 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.");
} }
} }
@ -374,6 +382,33 @@ namespace realm {
return object; return object;
} }
template<typename ValueType, typename ContextType>
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<typename ValueType, typename ContextType>
inline size_t Object::get_for_primary_key_impl(ContextType ctx, const ConstTableRef &table, const Property &primary_prop, ValueType primary_value) {
using Accessor = NativeAccessor<ValueType, ContextType>;
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() { inline void Object::verify_attached() {
if (!m_row.is_attached()) { if (!m_row.is_attached()) {
throw InvalidatedObjectException(m_object_schema->name, throw InvalidatedObjectException(m_object_schema->name,

View File

@ -48,7 +48,8 @@ class Arguments {
template<typename ValueType, typename ContextType> template<typename ValueType, typename ContextType>
class ArgumentConverter : public Arguments { class ArgumentConverter : public Arguments {
public: public:
ArgumentConverter(ContextType context, std::vector<ValueType> arguments) : m_arguments(arguments), m_ctx(context) {} ArgumentConverter(ContextType context, SharedRealm realm, std::vector<ValueType> arguments)
: m_arguments(arguments), m_ctx(context), m_realm(std::move(realm)) {}
using Accessor = realm::NativeAccessor<ValueType, ContextType>; using Accessor = realm::NativeAccessor<ValueType, ContextType>;
virtual bool bool_for_argument(size_t argument_index) { return Accessor::to_bool(m_ctx, argument_at(argument_index)); } 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 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 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 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)); } virtual bool is_argument_null(size_t argument_index) { return Accessor::is_null(m_ctx, argument_at(argument_index)); }
private: private:
std::vector<ValueType> m_arguments; std::vector<ValueType> m_arguments;
ContextType m_ctx; ContextType m_ctx;
SharedRealm m_realm;
ValueType &argument_at(size_t index) { ValueType &argument_at(size_t index) {
return m_arguments.at(index); return m_arguments.at(index);

View File

@ -28,6 +28,11 @@ const mockery = require('mockery');
function runTests() { function runTests() {
const Realm = require('realm'); const Realm = require('realm');
const RealmTests = require('./js'); const RealmTests = require('./js');
RealmTests.registerTests({
WorkerTests: require('./js/worker-tests'),
});
const testNames = RealmTests.getTestNames(); const testNames = RealmTests.getTestNames();
let passed = true; let passed = true;
@ -50,28 +55,27 @@ function runTests() {
} }
}; };
for (let suiteName in testNames) { return Object.keys(testNames).reduce((suitePromiseChain, suiteName) => {
return suitePromiseChain.then(() => {
console.log('Starting ' + suiteName); console.log('Starting ' + suiteName);
for (let testName of testNames[suiteName]) { return testNames[suiteName].reduce((testPromiseChain, testName) => {
RealmTests.runTest(suiteName, 'beforeEach'); return testPromiseChain.then(() => {
return RealmTests.runTest(suiteName, 'beforeEach');
try { }).then(() => {
RealmTests.runTest(suiteName, testName); return RealmTests.runTest(suiteName, testName);
}).then(() => {
console.log('+ ' + testName); console.log('+ ' + testName);
} }, (err) => {
catch (e) {
console.warn('- ' + testName); console.warn('- ' + testName);
console.error(e.message, e.stack); console.warn(err.message || err);
passed = false; passed = false;
} }).then(() => {
finally { return RealmTests.runTest(suiteName, 'afterEach');
RealmTests.runTest(suiteName, 'afterEach'); });
} }, Promise.resolve());
} });
} }, Promise.resolve()).then(() => passed);
return passed;
} }
if (require.main == module) { if (require.main == module) {
@ -79,7 +83,15 @@ if (require.main == module) {
mockery.warnOnUnregistered(false); mockery.warnOnUnregistered(false);
mockery.registerMock('realm', require('..')); mockery.registerMock('realm', require('..'));
if (!runTests()) { runTests().then(
(passed) => {
if (!passed) {
process.exit(1); process.exit(1);
} }
},
(err) => {
console.error(err);
process.exit(1);
}
);
} }

View File

@ -63,11 +63,25 @@ exports.runTest = function(suiteName, testName) {
// Start fresh in case of a crash in a previous run. // Start fresh in case of a crash in a previous run.
Realm.clearTestState(); Realm.clearTestState();
var promise;
try { 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 { } finally {
// Synchronously clear state if the test is not async.
if (!promise) {
Realm.clearTestState(); Realm.clearTestState();
} }
}
} else if (!testSuite || !(testName in SPECIAL_METHODS)) { } else if (!testSuite || !(testName in SPECIAL_METHODS)) {
throw new Error('Missing test: ' + suiteName + '.' + testName); throw new Error('Missing test: ' + suiteName + '.' + testName);
} }

View File

@ -328,6 +328,17 @@ module.exports = {
TestCase.assertEqual(obj.arrayCol[0].doubleCol, 3); TestCase.assertEqual(obj.arrayCol[0].doubleCol, 3);
TestCase.assertEqual(obj.arrayCol[1].doubleCol, 1); TestCase.assertEqual(obj.arrayCol[1].doubleCol, 1);
TestCase.assertEqual(obj.arrayCol[2].doubleCol, 2); 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() { testEnumerablePropertyNames: function() {
var realm = new Realm({schema: [schemas.BasicTypes]}); var realm = new Realm({schema: [schemas.BasicTypes]});

View File

@ -145,14 +145,19 @@ module.exports = {
}, },
testDefaultPath: function() { testDefaultPath: function() {
var defaultPath = Realm.defaultPath;
var defaultRealm = new Realm({schema: []}); var defaultRealm = new Realm({schema: []});
TestCase.assertEqual(defaultRealm.path, Realm.defaultPath); TestCase.assertEqual(defaultRealm.path, Realm.defaultPath);
var newPath = Realm.defaultPath.substring(0, Realm.defaultPath.lastIndexOf("/") + 1) + 'default2.realm'; try {
var newPath = Realm.defaultPath.substring(0, defaultPath.lastIndexOf('/') + 1) + 'default2.realm';
Realm.defaultPath = newPath; Realm.defaultPath = newPath;
defaultRealm = new Realm({schema: []}); defaultRealm = new Realm({schema: []});
TestCase.assertEqual(defaultRealm.path, newPath, "should use updated default realm path"); TestCase.assertEqual(defaultRealm.path, newPath, "should use updated default realm path");
TestCase.assertEqual(Realm.defaultPath, newPath, "defaultPath should have been updated"); TestCase.assertEqual(Realm.defaultPath, newPath, "defaultPath should have been updated");
} finally {
Realm.defaultPath = defaultPath;
}
}, },
testRealmSchemaVersion: function() { testRealmSchemaVersion: function() {
@ -273,7 +278,7 @@ module.exports = {
}, },
testRealmCreateUpsert: function() { 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() { realm.write(function() {
var values = { var values = {
primaryCol: '0', primaryCol: '0',
@ -360,6 +365,19 @@ module.exports = {
realm.create('AllTypesObject', {primaryCol: '1', objectCol: null}, true); realm.create('AllTypesObject', {primaryCol: '1', objectCol: null}, true);
TestCase.assertEqual(obj0.objectCol, null); TestCase.assertEqual(obj0.objectCol, null);
TestCase.assertEqual(obj1.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() { testNotifications: function() {
var realm = new Realm({schema: []}); var realm = new Realm({schema: []});
var notificationCount = 0; var notificationCount = 0;

View File

@ -130,6 +130,7 @@ module.exports = {
testResultsFiltered: function() { testResultsFiltered: function() {
var realm = new Realm({schema: [schemas.PersonObject, schemas.DefaultValues, schemas.TestObject]}); var realm = new Realm({schema: [schemas.PersonObject, schemas.DefaultValues, schemas.TestObject]});
realm.write(function() { realm.write(function() {
realm.create('PersonObject', {name: 'Ari', age: 10}); realm.create('PersonObject', {name: 'Ari', age: 10});
realm.create('PersonObject', {name: 'Tim', age: 11}); 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('name = $0', 'Tim').length, 1);
TestCase.assertEqual(realm.objects('PersonObject').filtered('age > $1 && age < $0', 13, 10).length, 3); TestCase.assertEqual(realm.objects('PersonObject').filtered('age > $1 && age < $0', 13, 10).length, 3);
TestCase.assertThrows(function() { TestCase.assertThrows(function() {
realm.objects('PersonObject').filtered('age > $2 && age < $0', 13, 10) realm.objects('PersonObject').filtered('age > $2 && age < $0', 13, 10)
}); });
TestCase.assertThrows(function() {
realm.objects('PersonObject').filtered("invalidQuery");
});
realm.write(function() { realm.write(function() {
realm.create('DefaultValuesObject', {'dateCol': new Date(3)}); 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, 1);
TestCase.assertEqual(realm.objects('DefaultValuesObject').filtered('dateCol <= $0', new Date(4)).length, 2); 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() { TestCase.assertThrows(function() {
realm.objects('PersonObject').filtered("invalidQuery"); realm.objects('LinkTypesObject').filtered('objectCol = $0', object);
}); });
}, },

View File

@ -106,6 +106,15 @@ exports.IntPrimary = {
} }
}; };
exports.StringPrimary = {
name: 'StringPrimaryObject',
primaryKey: 'primaryCol',
properties: {
primaryCol: Realm.Types.STRING,
valueCol: Realm.Types.INT,
}
};
exports.AllTypes = { exports.AllTypes = {
name: 'AllTypesObject', name: 'AllTypesObject',
primaryKey: 'primaryCol', primaryKey: 'primaryCol',

View File

@ -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};
}

76
tests/js/worker-tests.js Normal file
View File

@ -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,
}
});
});
}
};

44
tests/js/worker.js Normal file
View File

@ -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;

View File

@ -15,11 +15,6 @@
# Ignore react and fbjs where there are overlaps, but don't ignore # Ignore react and fbjs where there are overlaps, but don't ignore
# anything that react-native relies on # anything that react-native relies on
.*/node_modules/fbjs/lib/Map.js .*/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 .*/node_modules/fbjs/lib/ErrorUtils.js
# Flow has a built-in definition for the 'react' module which we prefer to use # 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/React.js
.*/node_modules/react/lib/ReactDOM.js .*/node_modules/react/lib/ReactDOM.js
.*/__mocks__/.*
.*/__tests__/.*
.*/commoner/test/source/widget/share.js
# Ignore commoner tests # Ignore commoner tests
.*/node_modules/commoner/test/.* .*/node_modules/commoner/test/.*
@ -40,26 +40,58 @@
# Ignore Website # Ignore Website
.*/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] [include]
[libs] [libs]
node_modules/react-native/Libraries/react-native/react-native-interface.js node_modules/react-native/Libraries/react-native/react-native-interface.js
node_modules/react-native/flow
flow/
[options] [options]
module.system=haste module.system=haste
esproposal.class_static_fields=enable
esproposal.class_instance_fields=enable
munge_underscores=true munge_underscores=true
module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub' 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=$FlowIssue
suppress_type=$FlowFixMe suppress_type=$FlowFixMe
suppress_type=$FixMe 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\\)*\\$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-1]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ 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 suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
[version] [version]
0.21.0 ^0.25.0

View File

@ -51,9 +51,9 @@
-keepattributes Signature -keepattributes Signature
-keepattributes *Annotation* -keepattributes *Annotation*
-keep class com.squareup.okhttp.** { *; } -keep class okhttp3.** { *; }
-keep interface com.squareup.okhttp.** { *; } -keep interface okhttp3.** { *; }
-dontwarn com.squareup.okhttp.** -dontwarn okhttp3.**
# okio # okio
@ -61,7 +61,3 @@
-dontwarn java.nio.file.* -dontwarn java.nio.file.*
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
-dontwarn okio.** -dontwarn okio.**
# stetho
-dontwarn com.facebook.stetho.**

View File

@ -48,7 +48,7 @@ async function runTests() {
itemTest.att('name', testName); itemTest.att('name', testName);
try { try {
runTest(suiteName, testName); await runTest(suiteName, testName);
} }
catch (e) { catch (e) {
itemTest.ele('error', {'message': ''}, e.message); itemTest.ele('error', {'message': ''}, e.message);

View File

@ -6,8 +6,8 @@
"start": "react-native start" "start": "react-native start"
}, },
"dependencies": { "dependencies": {
"react": "^0.14.8", "react": "15.1.0",
"react-native": "^0.25.1", "react-native": "^0.27.1",
"react-native-fs": "^1.1.0", "react-native-fs": "^1.1.0",
"xmlbuilder": "^4.2.1", "xmlbuilder": "^4.2.1",
"realm": "file:../..", "realm": "file:../..",

View File

@ -27,10 +27,10 @@ RealmTests.registerTests({
}); });
// Listen for event to run a particular test. // Listen for event to run a particular test.
NativeAppEventEmitter.addListener('realm-run-test', (test) => { NativeAppEventEmitter.addListener('realm-run-test', async ({suite, name}) => {
let error; let error;
try { try {
RealmTests.runTest(test.suite, test.name); await RealmTests.runTest(suite, name);
} catch (e) { } catch (e) {
error = '' + e; error = '' + e;
} }
@ -50,23 +50,23 @@ export function getTestNames() {
return RealmTests.getTestNames(); return RealmTests.getTestNames();
} }
export function runTests() { export async function runTests() {
let testNames = getTestNames(); let testNames = getTestNames();
for (let suiteName in testNames) { for (let suiteName in testNames) {
console.log('Starting ' + suiteName); console.log('Starting ' + suiteName);
for (let testName of testNames[suiteName]) { for (let testName of testNames[suiteName]) {
runTest(suiteName, testName); await runTest(suiteName, testName);
} }
} }
} }
export function runTest(suiteName, testName) { export async function runTest(suiteName, testName) {
RealmTests.runTest(suiteName, 'beforeEach'); await RealmTests.runTest(suiteName, 'beforeEach');
try { try {
RealmTests.runTest(suiteName, testName); await RealmTests.runTest(suiteName, testName);
console.log('+ ' + testName); console.log('+ ' + testName);
} }
catch (e) { catch (e) {
@ -75,6 +75,6 @@ export function runTest(suiteName, testName) {
throw e; throw e;
} }
finally { finally {
RealmTests.runTest(suiteName, 'afterEach'); await RealmTests.runTest(suiteName, 'afterEach');
} }
} }