diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 95a8b062..17ab0c7a 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -40,6 +40,6 @@ Full projects that we can compile and run ourselves are ideal!
## Version of Realm and Tooling
- Realm JS SDK Version: ?
-- Node or React Nattive: ?
+- Node or React Native: ?
- Client OS & Version: ?
- Which debugger for React Native: ?/None
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b04281cc..8672dfd4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,18 @@
+2.0.0 Release notes (2017-9-26)
+=============================================================
+### Breaking changes
+* None
+
+### Enhancements
+* Add a callback function used to verify SSL certificates in the sync config.
+
+### Bug fixes
+* Fixed port conflict between RN >= 0.48 inspector proxy and RPC server used for Chrome debugging (#1294).
+
+### Internal
+* Alignment of permission schemas.
+* Updating sync (2.0.0-rc24).
+
2.0.0-rc10 Release notes (2017-9-19)
=============================================================
### Breaking changes
@@ -15,7 +30,7 @@
### Enhancements
* Improve performance of the RPC worker for chrome debugging.
* Added Progress API `realm.syncSession.addProgressNotification` and `realm.syncSession.removeProgressNotification`
-* Added additional parameter for `Realm.open` and `Realm.openAsync` for download progress notifications
+* Added additional parameter for `Realm.open` and `Realm.openAsync` for download progress notifications
* Added `Realm.deleteFile` for deleting a Realm (#363).
* Added `Realm.deleteModel` for deleting a Realm model in a migration (#573).
* Added support for in-memory Realms.
@@ -150,7 +165,7 @@
* Added `indexOf()` method on `Realm.Results` and `Realm.List` that returns the index of the object in the collection.
### Bug fixes
-* Fix opening synced realms with a logged-in admin user.
+* Fix opening synced realms with a logged-in admin user.
1.8.1 Release notes (2017-6-20)
=============================================================
@@ -164,7 +179,7 @@
* Added `objectSchema()` method on `Realm.Object` that returns the schema for the object.
### Bug fixes
-* Fix `Realm.Sync.User.prototype.isAdmin` returning `false` for logged-in admin users.
+* Fix `Realm.Sync.User.prototype.isAdmin` returning `false` for logged-in admin users.
1.8.0 Release notes (2017-6-15)
=============================================================
diff --git a/dependencies.list b/dependencies.list
index 838e5511..d8a32030 100644
--- a/dependencies.list
+++ b/dependencies.list
@@ -1,5 +1,5 @@
PACKAGE_NAME=realm-js
-VERSION=2.0.0-rc10
+VERSION=2.0.0-rc11
REALM_CORE_VERSION=3.2.1
-REALM_SYNC_VERSION=2.0.0-rc22
+REALM_SYNC_VERSION=2.0.0-rc24
REALM_OBJECT_SERVER_VERSION=2.0.0-alpha.36
diff --git a/docs/realm.js b/docs/realm.js
index 63c14ad5..e379d1c7 100644
--- a/docs/realm.js
+++ b/docs/realm.js
@@ -92,17 +92,17 @@ class Realm {
constructor(config) {}
/**
- * Open a realm asynchronously with a promise. If the realm is synced, it will be fully
+ * Open a Realm asynchronously with a promise. If the Realm is synced, it will be fully
* synchronized before it is available.
- * @param {Realm~Configuration} config
+ * @param {Realm~Configuration} config
* @returns {ProgressPromise} - a promise that will be resolved with the realm instance when it's available.
*/
static open(config) {}
/**
- * Open a realm asynchronously with a callback. If the realm is synced, it will be fully
+ * Open a Realm asynchronously with a callback. If the Realm is synced, it will be fully
* synchronized before it is available.
- * @param {Realm~Configuration} config
+ * @param {Realm~Configuration} config
* @param {callback(error, realm)} - will be called when the realm is ready.
* @param {callback(transferred, transferable)} [progressCallback] - an optional callback for download progress notifications
* @throws {Error} If anything in the provided `config` is invalid.
@@ -217,7 +217,7 @@ class Realm {
/*
* Replaces all string columns in this Realm with a string enumeration column and compacts the
* database file.
- *
+ *
* Cannot be called from a write transaction.
*
* Compaction will not occur if other `Realm` instances exist.
@@ -269,12 +269,12 @@ Realm.defaultPath;
* This function takes two arguments:
* - `oldRealm` - The Realm before migration is performed.
* - `newRealm` - The Realm that uses the latest `schema`, which should be modified as necessary.
- * @property {callback(number, number)} [shouldCompactOnLaunch] - The function called when opening
- * a Realm for the first time during the life of a process to determine if it should be compacted
+ * @property {callback(number, number)} [shouldCompactOnLaunch] - The function called when opening
+ * a Realm for the first time during the life of a process to determine if it should be compacted
* before being returned to the user. The function takes two arguments:
- * - `totalSize` - The total file size (data + free space)
+ * - `totalSize` - The total file size (data + free space)
* - `unusedSize` - The total bytes used by data in the file.
- * It returns `true` to indicate that an attempt to compact the file should be made. The compaction
+ * It returns `true` to indicate that an attempt to compact the file should be made. The compaction
* will be skipped if another process is accessing it.
* @property {string} [path={@link Realm.defaultPath}] - The path to the file where the
* Realm database should be stored.
@@ -288,14 +288,49 @@ Realm.defaultPath;
* object types in this Realm. **Required** when first creating a Realm at this `path`.
* @property {number} [schemaVersion] - **Required** (and must be incremented) after
* changing the `schema`.
- * @property {Object} [sync] - Sync configuration parameters with the following
+ * @property {Object} [sync] - Sync configuration parameters with the following
* child properties:
* - `user` - A `User` object obtained by calling `Realm.Sync.User.login`
* - `url` - A `string` which contains a valid Realm Sync url
- * - `error` - A callback function which is called in error situations
+ * - `error` - A callback function which is called in error situations.
+ * The `error` callback can take up to four optional arguments: `message`, `isFatal`,
+ * `category`, and `code`.
* - `validate_ssl` - Indicating if SSL certificates must be validated
* - `ssl_trust_certificate_path` - A path where to find trusted SSL certificates
- * The `error` callback can take up to four optional arguments: `message`, `isFatal`, `category`, and `code`.
+ * - `open_ssl_verify_callback` - A callback function used to accept or reject the server's
+ * SSL certificate. open_ssl_verify_callback is called with an object of type
+ *
+ * {
+ * serverAddress: String,
+ * serverPort: Number,
+ * pemCertificate: String,
+ * acceptedByOpenSSL: Boolean,
+ * depth: Number
+ * }
+ *
+ * The return value of open_ssl_verify_callback decides whether the certificate is accepted (true)
+ * or rejected (false). The open_ssl_verify_callback function is only respected on platforms where
+ * OpenSSL is used for the sync client, e.g. Linux. The open_ssl_verify_callback function is not
+ * allowed to throw exceptions. If the operations needed to verify the certificate lead to an exception,
+ * the exception must be caught explicitly before returning. The return value would typically be false
+ * in case of an exception.
+ *
+ * When the sync client has received the server's certificate chain, it presents every certificate in
+ * the chain to the open_ssl_verify_callback function. The depth argument specifies the position of the
+ * certificate in the chain. depth = 0 represents the actual server certificate. The root
+ * certificate has the highest depth. The certificate of highest depth will be presented first.
+ *
+ * acceptedByOpenSSL is true if OpenSSL has accepted the certificate, and false if OpenSSL has rejected it.
+ * It is generally safe to return true when acceptedByOpenSSL is true. If acceptedByOpenSSL is false, an
+ * independent verification should be made.
+ *
+ * One possible way of using the open_ssl_verify_callback function is to embed the known server certificate
+ * in the client and accept the presented certificate if and only if it is equal to the known certificate.
+ *
+ * The purpose of open_ssl_verify_callback is to enable custom certificate handling and to solve cases where
+ * OpenSSL erroneously rejects valid certificates possibly because OpenSSL doesn't have access to the
+ * proper trust certificates.
+ *
*/
/**
@@ -329,7 +364,7 @@ Realm.defaultPath;
* otherwise specified.
* @property {boolean} [optional] - Signals if this property may be assigned `null` or `undefined`.
* @property {boolean} [indexed] - Signals if this property should be indexed. Only supported for
- * `"string"`, `"int"`, and `"bool"` properties.
+ * `"string"`, `"int"`, and `"bool"` properties.
*/
/**
diff --git a/docs/sync.js b/docs/sync.js
index 76d20ef3..3b271d5a 100644
--- a/docs/sync.js
+++ b/docs/sync.js
@@ -30,9 +30,6 @@ class Sync {
* _Currently only the 'change' event is supported_
* @param {function(change_event)} change_callback - called when changes are made to any Realm which
* match the given regular expression
- * @param {bool} validate_ssl=true - Validate the server's SSL chertificate.
- * @param {string} ssl_trust_certificate_path=None - Path to a trust/anchor certificate used by the
- * client to verify the server certificate.
*/
static addListener(server_url, admin_user, regex, name, change_callback) {}
diff --git a/lib/browser/index.js b/lib/browser/index.js
index 10bc7512..8ef9fc12 100644
--- a/lib/browser/index.js
+++ b/lib/browser/index.js
@@ -83,14 +83,14 @@ export default class Realm {
if (typeof item == 'function') {
let schema = item.schema;
if (!schema || typeof schema != 'object') {
- throw new Error("Realm object constructor must have 'schema' property");
+ throw new Error("Realm object constructor must have a 'schema' property.");
}
let {name, properties} = schema;
if (!name || typeof name != 'string') {
- throw new Error("Realm object schema must have 'name' property");
+ throw new Error(`Failed to read ObjectSchema: name must be of type 'string', got (${typeof name})`);
} else if (!properties || typeof properties != 'object') {
- throw new Error("Realm object schema must have 'properties' property");
+ throw new Error(`Failed to read ObjectSchema: properties must be of type 'object', got (${typeof properties})`);
}
schemas.splice(i, 1, schema);
diff --git a/lib/browser/objects.js b/lib/browser/objects.js
index f0f5caf7..9c9ad87e 100644
--- a/lib/browser/objects.js
+++ b/lib/browser/objects.js
@@ -85,5 +85,5 @@ export function typeForConstructor(realmId, constructor) {
}
}
- return null;
+ throw new Error("Constructor was not registered in the schema for this Realm")
}
diff --git a/lib/index.d.ts b/lib/index.d.ts
index 941fe647..76106fe4 100644
--- a/lib/index.d.ts
+++ b/lib/index.d.ts
@@ -265,25 +265,25 @@ declare namespace Realm.Sync {
readonly server: string;
readonly token: string;
static adminUser(adminToken: string, server?: string): User;
-
+
/**
* @deprecated, to be removed in future versions
*/
static login(server: string, username: string, password: string, callback: (error: any, user: User) => void): void;
static login(server: string, username: string, password: string): Promise;
-
+
/**
* @deprecated, to be removed in future versions
- */
+ */
static register(server: string, username: string, password: string, callback: (error: any, user: User) => void): void;
static register(server: string, username: string, password: string): Promise;
-
+
/**
* @deprecated, to be removed in versions
- */
+ */
static registerWithProvider(server: string, options: { provider: string, providerToken: string, userInfo: any }, callback: (error: Error | null, user: User | null) => void): void;
static registerWithProvider(server: string, options: { provider: string, providerToken: string, userInfo: any }): Promise;
-
+
logout(): void;
openManagementRealm(): Realm;
retrieveAccount(provider: string, username: string): Promise;
@@ -299,7 +299,7 @@ declare namespace Realm.Sync {
userId: string |
{ metadataKey: string, metadataValue: string }
};
-
+
type AccessLevel = 'none' | 'read' | 'write' | 'admin';
class Permission {
@@ -310,7 +310,7 @@ declare namespace Realm.Sync {
readonly mayRead?: boolean;
readonly mayWrite?: boolean;
readonly mayManage?: boolean;
- }
+ }
class PermissionChange {
id: string;
@@ -342,19 +342,21 @@ declare namespace Realm.Sync {
}
type ErrorCallback = (message?: string, isFatal?: boolean, category?: string, code?: number) => void;
+ type SSLVerifyCallback = (serverAddress: string, serverPort: number, pemCertificate: string, preverifyOk: number, depth: number) => boolean;
interface SyncConfiguration {
user: User;
url: string;
validate_ssl?: boolean;
ssl_trust_certificate_path?: string;
+ ssl_verify_callback?: SSLVerifyCallback;
error?: ErrorCallback;
}
type ProgressNotificationCallback = (transferred: number, transferable: number) => void;
type ProgressDirection = 'download' | 'upload';
type ProgressMode = 'reportIndefinitely' | 'forCurrentlyOutstandingWork';
-
+
/**
* Session
* @see { @link https://realm.io/docs/javascript/latest/api/Realm.Sync.Session.html }
@@ -394,7 +396,7 @@ declare namespace Realm.Sync {
function removeListener(regex: string, name: string, changeCallback: (changeEvent: ChangeEvent) => void): void;
function setLogLevel(logLevel: 'all' | 'trace' | 'debug' | 'detail' | 'info' | 'warn' | 'error' | 'fatal' | 'off'): void;
function setFeatureToken(token: string): void;
-
+
/**
* @deprecated, to be removed in 2.0
*/
@@ -458,19 +460,19 @@ declare class Realm {
*/
static schemaVersion(path: string, encryptionKey?: ArrayBuffer | ArrayBufferView): number;
-
+
/**
* Open a realm asynchronously with a promise. If the realm is synced, it will be fully synchronized before it is available.
- * @param {Configuration} config
+ * @param {Configuration} config
*/
static open(config: Realm.Configuration): ProgressPromise;
/**
* @deprecated in favor of `Realm.open`
* Open a realm asynchronously with a callback. If the realm is synced, it will be fully synchronized before it is available.
- * @param {Configuration} config
+ * @param {Configuration} config
* @param {Function} callback will be called when the realm is ready.
- * @param {ProgressNotificationCallback} progressCallback? a progress notification callback for 'download' direction and 'forCurrentlyOutstandingWork' mode
+ * @param {ProgressNotificationCallback} progressCallback? a progress notification callback for 'download' direction and 'forCurrentlyOutstandingWork' mode
*/
static openAsync(config: Realm.Configuration, callback: (error: any, realm: Realm) => void, progressCallback?: Realm.Sync.ProgressNotificationCallback): void
diff --git a/lib/management-schema.js b/lib/management-schema.js
index 3d14b80e..bb7afa0b 100644
--- a/lib/management-schema.js
+++ b/lib/management-schema.js
@@ -21,50 +21,50 @@
module.exports = [
{
name: 'PermissionChange',
+ primaryKey: 'id',
properties: {
- id: { type: 'string' },
- createdAt: { type: 'date' },
- updatedAt: { type: 'date' },
- statusCode: { type: 'int', optional: true },
- statusMessage: { type: 'string', optional: true },
- userId: { type: 'string' },
- metadataKey: { type: 'string', optional: true },
+ id: {type: 'string'},
+ createdAt: {type: 'date', default: new Date()},
+ updatedAt: {type: 'date', default: new Date()},
+ statusCode: { type: 'int', optional: true },
+ statusMessage: {type: 'string', optional: true},
+ userId: { type: 'string' },
+ realmUrl: { type: 'string' },
+ metadataKey: { type: 'string', optional: true },
metadataValue: { type: 'string', optional: true },
- realmUrl: { type: 'string' },
- mayRead: { type: 'bool', optional: true },
- mayWrite: { type: 'bool', optional: true },
- mayManage: { type: 'bool', optional: true },
- },
- primaryKey: 'id'
+ mayRead: { type: 'bool', optional: true },
+ mayWrite: { type: 'bool', optional: true },
+ mayManage: { type: 'bool', optional: true },
+ }
},
{
name: 'PermissionOffer',
+ primaryKey: 'id',
properties: {
- id: { type: 'string' },
- createdAt: { type: 'date' },
- updatedAt: { type: 'date' },
- statusCode: { type: 'int', optional: true },
- statusMessage: { type: 'string', optional: true },
- token: { type: 'string', optional: true, indexed: true },
- realmUrl: { type: 'string' },
- mayRead: { type: 'bool', default: false },
- mayWrite: { type: 'bool', default: false },
- mayManage: { type: 'bool', default: false },
- expiresAt: { type: 'date', optional: true },
- },
- primaryKey: 'id'
+ id: { type: 'string', optional: false, indexed: true },
+ createdAt: {type: 'date', default: new Date()},
+ updatedAt: {type: 'date', default: new Date()},
+ statusCode: { type: 'int', optional: true },
+ statusMessage: {type: 'string', optional: true},
+ token: { type: 'string', optional: true, indexed: true },
+ realmUrl: { type: 'string' },
+ mayRead: { type: 'bool', default: false },
+ mayWrite: { type: 'bool', default: false },
+ mayManage: { type: 'bool', default: false },
+ expiresAt: { type: 'date', optional: true }
+ }
},
{
name: 'PermissionOfferResponse',
+ primaryKey: 'id',
properties: {
- id: { type: 'string' },
- createdAt: { type: 'date' },
- updatedAt: { type: 'date' },
- statusCode: { type: 'int', optional: true },
- statusMessage: { type: 'string', optional: true },
- token: { type: 'string' },
- realmUrl: { type: 'string', optional: true },
- },
- primaryKey: 'id'
+ id: { type: 'string', optional: false },
+ createdAt: {type: 'date', default: new Date()},
+ updatedAt: {type: 'date', default: new Date()},
+ statusCode: { type: 'int', optional: true },
+ statusMessage: {type: 'string', optional: true},
+ token: { type: 'string' },
+ realmUrl: { type: 'string', optional: true }
+ }
}
];
diff --git a/lib/permission-api.js b/lib/permission-api.js
index 2df3491a..4cdff8da 100644
--- a/lib/permission-api.js
+++ b/lib/permission-api.js
@@ -29,20 +29,17 @@ function generateUniqueId() {
return uuid;
}
-const permissionSchema = [
- {
+const permissionSchema = [{
name: 'Permission',
properties: {
- id: { type: 'string' },
- updatedAt: { type: 'date' },
- userId: { type: 'string' },
- path: { type: 'string' },
- mayRead: { type: 'bool' },
- mayWrite: { type: 'bool' },
- mayManage: { type: 'bool' },
+ userId: {type: 'string' },
+ path: { type: 'string' },
+ mayRead: { type: 'bool', optional: false },
+ mayWrite: { type: 'bool', optional: false },
+ mayManage: { type: 'bool', optional: false },
+ updatedAt: { type: 'date', optional: false },
}
- }
-];
+}];
// Symbols are not supported on RN yet, so we use this for now:
const specialPurposeRealmsKey = '_specialPurposeRealms';
@@ -81,7 +78,7 @@ function getSpecialPurposeRealm(user, realmName, schema) {
_Realm._waitForDownload(config, (error) => {
// FIXME: I don't understand why, but removing the following setTimeout causes the subsequent
- // setTimeout call (when resolving the promise) to hang on RN iOS.
+ // setTimeout call (when resolving the promise) to hang on RN iOS.
// This might be related to our general makeCallback issue: #1255.
setTimeout(() => {}, 1);
@@ -108,7 +105,7 @@ function createInManagementRealm(user, modelName, modelInitializer) {
return new Promise((resolve, reject) => {
try {
let o;
-
+
const listener = () => {
if (!o) {
return;
@@ -156,7 +153,7 @@ module.exports = {
.then(permissionRealm => {
let permissions = permissionRealm.objects('Permission')
.filtered('NOT path ENDSWITH "__permission" AND NOT path ENDSWITH "__management"');
-
+
if (recipient === 'currentUser') {
permissions = permissions.filtered('userId = $0', this.identity);
}
@@ -234,7 +231,7 @@ module.exports = {
if (!token) {
return Promise.reject(new Error('Offer token must be specified'));
}
-
+
const permissionOfferResponse = {
id: generateUniqueId(),
createdAt: new Date(),
@@ -255,7 +252,7 @@ module.exports = {
// We were given a token, not an object. Find the matching object.
const q = managementRealm.objects('PermissionOffer')
.filtered('token = $0', permissionOfferOrToken);
-
+
if (q.length === 0) {
throw new Error("No permission offers with the given token were found");
}
diff --git a/package.json b/package.json
index c14bf2e3..012a4e95 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "realm",
"description": "Realm is a mobile database: an alternative to SQLite and key-value stores",
- "version": "2.0.0-rc10",
+ "version": "2.0.0-rc11",
"license": "Apache-2.0",
"homepage": "https://realm.io",
"keywords": [
@@ -59,9 +59,9 @@
"jsdoc": "npm install && npm run jsdoc:clean && jsdoc -u docs/tutorials -p package.json -c docs/conf.json",
"prenode-tests": "npm install --build-from-source=realm && cd tests && npm install",
"node-tests": "cd tests && npm run test && cd ..",
- "test-runner:ava": "cd tests/test-runners/ava && npm install && npm test",
- "test-runner:mocha": "cd tests/test-runners/mocha && npm install && npm test",
- "test-runner:jest": "cd tests/test-runners/jest && npm install && npm test",
+ "test-runner:ava": "cd tests/test-runners/ava && npm install --build-from-source=realm && npm test",
+ "test-runner:mocha": "cd tests/test-runners/mocha && npm install --build-from-source=realm && npm test",
+ "test-runner:jest": "cd tests/test-runners/jest && npm install --build-from-source=realm && npm test",
"test-runners": "npm run test-runner:ava && npm run test-runner:mocha && npm run test-runner:jest",
"isMac": "node -p \"if (process.platform == 'darwin') { process.exit(0); } else { process.exit(-1); }\"",
"testMac": "npm run isMac -s && echo this is mac || echo . ",
diff --git a/react-native/android/publish_android_template b/react-native/android/publish_android_template
index c4c0670b..7d1e6686 100644
--- a/react-native/android/publish_android_template
+++ b/react-native/android/publish_android_template
@@ -22,17 +22,17 @@ apply plugin: 'com.android.library'
task forwardDebugPort(type: Exec) {
def adb = android.getAdbExe()?.toString() ?: 'false'
- commandLine adb, 'forward', 'tcp:8082', 'tcp:8082'
+ commandLine adb, 'forward', 'tcp:8083', 'tcp:8083'
ignoreExitValue true
doLast {
if (execResult.getExitValue() != 0) {
logger.error(
'===========================================================================\n' +
- 'WARNING: Failed to automatically forward port 8082.\n' +
- 'In order to use Realm in Chrome debugging mode, port 8082 must be forwarded\n' +
+ 'WARNING: Failed to automatically forward port 8083.\n' +
+ 'In order to use Realm in Chrome debugging mode, port 8083 must be forwarded\n' +
'from localhost to the device or emulator being used to run the application.\n' +
'You may need to add the appropriate flags to the command that failed:\n' +
- ' adb forward tcp:8082 tcp:8082\n' +
+ ' adb forward tcp:8083 tcp:8083\n' +
'===========================================================================\n'
)
}
diff --git a/react-native/android/src/main/java/io/realm/react/RealmReactModule.java b/react-native/android/src/main/java/io/realm/react/RealmReactModule.java
index 696b978d..0ad49a2a 100644
--- a/react-native/android/src/main/java/io/realm/react/RealmReactModule.java
+++ b/react-native/android/src/main/java/io/realm/react/RealmReactModule.java
@@ -23,7 +23,7 @@ import java.util.Map;
import fi.iki.elonen.NanoHTTPD;
class RealmReactModule extends ReactContextBaseJavaModule {
- private static final int DEFAULT_PORT = 8082;
+ private static final int DEFAULT_PORT = 8083;
private static boolean sentAnalytics = false;
private AndroidWebServer webServer;
diff --git a/react-native/ios/RealmReact/RealmReact.mm b/react-native/ios/RealmReact/RealmReact.mm
index 62be7893..26da98e2 100644
--- a/react-native/ios/RealmReact/RealmReact.mm
+++ b/react-native/ios/RealmReact/RealmReact.mm
@@ -38,7 +38,7 @@
#import "GCDWebServerErrorResponse.h"
#import "rpc.hpp"
-#define WEB_SERVER_PORT 8082
+#define WEB_SERVER_PORT 8083
using namespace realm::rpc;
#endif
diff --git a/scripts/test.sh b/scripts/test.sh
index 6fb10a4a..0aac32ec 100755
--- a/scripts/test.sh
+++ b/scripts/test.sh
@@ -9,7 +9,7 @@ export NPM_CONFIG_PROGRESS=false
TARGET=$1
CONFIGURATION=${2:-Release}
-if echo $CONFIGURATION | grep -i "^Debug$" > /dev/null ; then
+if echo "$CONFIGURATION" | grep -i "^Debug$" > /dev/null ; then
CONFIGURATION="Debug"
fi
@@ -17,8 +17,6 @@ IOS_SIM_DEVICE=${IOS_SIM_DEVICE:-} # use preferentially, otherwise will be set a
ios_sim_default_device_type=${IOS_SIM_DEVICE_TYPE:-iPhone 5s}
ios_sim_default_ios_version=${IOS_SIM_OS:-iOS 10.1}
-ACCEPTED_LICENSES='MIT, ISC, BSD, Apache-2.0, BSD-2-Clause, BSD-3-Clause, WTFPL, Unlicense, (MIT AND CC-BY-3.0)'
-
PATH="/opt/android-sdk-linux/platform-tools:$PATH"
SRCROOT=$(cd "$(dirname "$0")/.." && pwd)
XCPRETTY=$(which xcpretty || true)
@@ -130,13 +128,18 @@ xctest() {
echo " done"
# - Run the build and test
+ xcrun xcodebuild -scheme "$1" -configuration "$CONFIGURATION" -sdk iphonesimulator -destination id="$IOS_SIM_DEVICE" build || {
+ EXITCODE=$?
+ echo "*** Failure (exit code $EXITCODE). ***"
+ exit $EXITCODE
+ }
if [ -n "$XCPRETTY" ]; then
log_temp=$(mktemp build.log.XXXXXX)
if [ -e "$log_temp" ]; then
rm "$log_temp"
fi
- xcrun xcodebuild -scheme "$1" -configuration "$CONFIGURATION" -sdk iphonesimulator -destination name="iPhone 5s" build test 2>&1 | tee "$log_temp" | "$XCPRETTY" -c --no-utf --report junit --output build/reports/junit.xml || {
- EXITCODE=$?
+ xcrun xcodebuild -scheme "$1" -configuration "$CONFIGURATION" -sdk iphonesimulator -destination name="iPhone 5s" test 2>&1 | tee "$log_temp" | "$XCPRETTY" -c --no-utf --report junit --output build/reports/junit.xml || {
+ EXITCODE=$?
printf "*** Xcode Failure (exit code %s). The full xcode log follows: ***\n\n" "$EXITCODE"
cat "$log_temp"
printf "\n\n*** End Xcode Failure ***\n"
@@ -144,11 +147,11 @@ xctest() {
}
rm "$log_temp"
else
- xcrun xcodebuild -scheme "$1" -configuration "$CONFIGURATION" -sdk iphonesimulator -destination id="$IOS_SIM_DEVICE" build test || {
- EXITCODE=$?
+ xcrun xcodebuild -scheme "$1" -configuration "$CONFIGURATION" -sdk iphonesimulator -destination id="$IOS_SIM_DEVICE" test || {
+ EXITCODE=$?
echo "*** Failure (exit code $EXITCODE). ***"
exit $EXITCODE
- }
+ }
fi
}
@@ -240,14 +243,22 @@ cleanup
trap cleanup EXIT
# Use a consistent version of Node if possible.
-if [ -f "$NVM_DIR/nvm.sh" ]; then
- . "$NVM_DIR/nvm.sh"
-elif [ -x "$(command -v brew)" ] && [ -f "$(brew --prefix nvm)/nvm.sh" ]; then
- # we must be on mac and nvm was installed with brew
- # TODO: change the mac slaves to use manual nvm installation
- . "$(brew --prefix nvm)/nvm.sh"
+if [[ -z "$(command -v nvm)" ]]; then
+ set +e
+ if [ -f "$NVM_DIR/nvm.sh" ]; then
+ . "$NVM_DIR/nvm.sh" '' || true
+ elif [ -x "$(command -v brew)" ] && [ -f "$(brew --prefix nvm)/nvm.sh" ]; then
+ # we must be on mac and nvm was installed with brew
+ # TODO: change the mac slaves to use manual nvm installation
+ . "$(brew --prefix nvm)/nvm.sh" '' || true
+ elif [ -f "$HOME/.nvm/nvm.sh" ]; then
+ . ~/.nvm/nvm.sh ''
+ fi
+ set -e
+fi
+if [[ "$(command -v nvm)" ]]; then
+ nvm install 7.10.0
fi
-[[ "$(command -v nvm)" ]] && nvm install 7.10.0 && nvm use 7.10.0 || true
# Remove cached packages
rm -rf ~/.yarn-cache/npm-realm-*
@@ -406,8 +417,6 @@ case "$TARGET" in
;;
"test-runners")
npm run check-environment
- # Create a fake realm module that points to the source root so that test-runner tests can require('realm')
- npm install --build-from-source=realm
npm run test-runners
;;
"all")
diff --git a/src/js_class.hpp b/src/js_class.hpp
index 70b28e2e..052ec8f5 100644
--- a/src/js_class.hpp
+++ b/src/js_class.hpp
@@ -33,6 +33,29 @@ using ConstructorType = void(typename T::Context, typename T::Object, size_t, co
template
using MethodType = void(typename T::Context, typename T::Function, typename T::Object, size_t, const typename T::Value[], ReturnValue &);
+template
+struct Arguments {
+ const typename T::Context ctx;
+ const size_t count;
+ const typename T::Value* const value;
+
+ typename T::Value operator[](size_t index) const noexcept {
+ if (index >= count) {
+ return Value::from_undefined(ctx);
+ }
+ return value[index];
+ }
+
+ void validate_maximum(size_t max) const {
+ if (max < count) {
+ throw std::invalid_argument(util::format("Invalid arguments: at most %1 expected, but %2 supplied.", max, count));
+ }
+ }
+};
+
+template
+using ArgumentsMethodType = void(typename T::Context, typename T::Function, typename T::Object, Arguments, ReturnValue &);
+
template
struct PropertyType {
using GetterType = void(typename T::Context, typename T::Object, ReturnValue &);
diff --git a/src/js_realm.hpp b/src/js_realm.hpp
index 5f22c677..90981bb9 100644
--- a/src/js_realm.hpp
+++ b/src/js_realm.hpp
@@ -123,9 +123,7 @@ class RealmDelegate : public BindingContext {
}
ObjectType realm_object = create_object>(m_context, new SharedRealm(realm));
- ValueType arguments[2];
- arguments[0] = realm_object;
- arguments[1] = Value::from_string(m_context, notification_name);
+ ValueType arguments[] = {realm_object, Value::from_string(m_context, notification_name)};
std::list> notifications_copy(m_notifications);
for (auto &callback : notifications_copy) {
@@ -148,6 +146,7 @@ class RealmClass : public ClassDefinition> {
using FunctionType = typename T::Function;
using ObjectType = typename T::Object;
using ValueType = typename T::Value;
+ using Arguments = js::Arguments;
using String = js::String;
using Object = js::Object;
using Value = js::Value;
@@ -165,22 +164,22 @@ public:
static FunctionType create_constructor(ContextType);
// methods
- static void objects(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
- static void object_for_primary_key(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
- static void create(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
- static void delete_one(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
- static void delete_all(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
- static void write(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
- static void begin_transaction(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue&);
- static void commit_transaction(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue&);
- static void cancel_transaction(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue&);
- static void add_listener(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
- static void wait_for_download_completion(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
- static void remove_listener(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
- static void remove_all_listeners(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
- static void close(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
- static void compact(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
- static void delete_model(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
+ static void objects(ContextType, FunctionType, ObjectType, Arguments, ReturnValue &);
+ static void object_for_primary_key(ContextType, FunctionType, ObjectType, Arguments, ReturnValue &);
+ static void create(ContextType, FunctionType, ObjectType, Arguments, ReturnValue &);
+ static void delete_one(ContextType, FunctionType, ObjectType, Arguments, ReturnValue &);
+ static void delete_all(ContextType, FunctionType, ObjectType, Arguments, ReturnValue &);
+ static void write(ContextType, FunctionType, ObjectType, Arguments, ReturnValue &);
+ static void begin_transaction(ContextType, FunctionType, ObjectType, Arguments, ReturnValue&);
+ static void commit_transaction(ContextType, FunctionType, ObjectType, Arguments, ReturnValue&);
+ static void cancel_transaction(ContextType, FunctionType, ObjectType, Arguments, ReturnValue&);
+ static void add_listener(ContextType, FunctionType, ObjectType, Arguments, ReturnValue &);
+ static void wait_for_download_completion(ContextType, FunctionType, ObjectType, Arguments, ReturnValue &);
+ static void remove_listener(ContextType, FunctionType, ObjectType, Arguments, ReturnValue &);
+ static void remove_all_listeners(ContextType, FunctionType, ObjectType, Arguments, ReturnValue &);
+ static void close(ContextType, FunctionType, ObjectType, Arguments, ReturnValue &);
+ static void compact(ContextType, FunctionType, ObjectType, Arguments, ReturnValue &);
+ static void delete_model(ContextType, FunctionType, ObjectType, Arguments, ReturnValue &);
// properties
static void get_empty(ContextType, ObjectType, ReturnValue &);
@@ -198,10 +197,10 @@ public:
static void constructor(ContextType, ObjectType, size_t, const ValueType[]);
static SharedRealm create_shared_realm(ContextType, realm::Realm::Config, bool, ObjectDefaultsMap &&, ConstructorMap &&);
- static void schema_version(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
- static void clear_test_state(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
- static void copy_bundled_realm_files(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
- static void delete_file(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
+ static void schema_version(ContextType, FunctionType, ObjectType, Arguments, ReturnValue &);
+ static void clear_test_state(ContextType, FunctionType, ObjectType, Arguments, ReturnValue &);
+ static void copy_bundled_realm_files(ContextType, FunctionType, ObjectType, Arguments, ReturnValue &);
+ static void delete_file(ContextType, FunctionType, ObjectType, Arguments, ReturnValue &);
// static properties
static void get_default_path(ContextType, ObjectType, ReturnValue &);
@@ -398,7 +397,7 @@ void RealmClass::constructor(ContextType ctx, ObjectType this_object, size_t
static const String schema_string = "schema";
ValueType schema_value = Object::get_property(ctx, object, schema_string);
if (!Value::is_undefined(ctx, schema_value)) {
- ObjectType schema_object = Value::validated_to_object(ctx, schema_value, "schema");
+ ObjectType schema_object = Value::validated_to_array(ctx, schema_value, "schema");
config.schema.emplace(Schema::parse_schema(ctx, schema_object, defaults, constructors));
schema_updated = true;
}
@@ -504,13 +503,13 @@ SharedRealm RealmClass::create_shared_realm(ContextType ctx, realm::Realm::Co
}
template
-void RealmClass::schema_version(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
- validate_argument_count(argc, 1, 2);
+void RealmClass::schema_version(ContextType ctx, FunctionType, ObjectType this_object, Arguments args, ReturnValue &return_value) {
+ args.validate_maximum(2);
realm::Realm::Config config;
- config.path = normalize_realm_path(Value::validated_to_string(ctx, arguments[0]));
- if (argc == 2) {
- auto encryption_key = Value::validated_to_binary(ctx, arguments[1], "encryptionKey");
+ config.path = normalize_realm_path(Value::validated_to_string(ctx, args[0]));
+ if (args.count == 2) {
+ auto encryption_key = Value::validated_to_binary(ctx, args[1], "encryptionKey");
config.encryption_key.assign(encryption_key.data(), encryption_key.data() + encryption_key.size());
}
@@ -525,23 +524,22 @@ void RealmClass::schema_version(ContextType ctx, FunctionType, ObjectType thi
template
-void RealmClass::clear_test_state(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
- validate_argument_count(argc, 0);
-
+void RealmClass::clear_test_state(ContextType ctx, FunctionType, ObjectType this_object, Arguments args, ReturnValue &return_value) {
+ args.validate_maximum(0);
js::clear_test_state();
}
template
-void RealmClass::copy_bundled_realm_files(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
- validate_argument_count(argc, 0);
+void RealmClass::copy_bundled_realm_files(ContextType ctx, FunctionType, ObjectType this_object, Arguments args, ReturnValue &return_value) {
+ args.validate_maximum(0);
realm::copy_bundled_realm_files();
}
template
-void RealmClass::delete_file(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
- validate_argument_count(argc, 1);
+void RealmClass::delete_file(ContextType ctx, FunctionType, ObjectType this_object, Arguments args, ReturnValue &return_value) {
+ args.validate_maximum(1);
- ValueType value = arguments[0];
+ ValueType value = args[0];
if (!Value::is_object(ctx, value)) {
throw std::runtime_error("Invalid argument, expected a Realm configuration object");
}
@@ -569,9 +567,9 @@ void RealmClass::delete_file(ContextType ctx, FunctionType, ObjectType this_o
}
template
-void RealmClass::delete_model(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
- validate_argument_count(argc, 1);
- ValueType value = arguments[0];
+void RealmClass::delete_model(ContextType ctx, FunctionType, ObjectType this_object, Arguments args, ReturnValue &return_value) {
+ args.validate_maximum(1);
+ ValueType value = args[0];
SharedRealm& realm = *get_internal>(this_object);
@@ -643,14 +641,14 @@ void RealmClass::get_sync_session(ContextType ctx, ObjectType object, ReturnV
#endif
template
-void RealmClass::wait_for_download_completion(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
- validate_argument_count(argc, 2, 3);
- auto config_object = Value::validated_to_object(ctx, arguments[0]);
- auto callback_function = Value::validated_to_function(ctx, arguments[argc - 1]);
+void RealmClass::wait_for_download_completion(ContextType ctx, FunctionType, ObjectType this_object, Arguments args, ReturnValue &return_value) {
+ args.validate_maximum(3);
+ auto config_object = Value::validated_to_object(ctx, args[0]);
+ auto callback_function = Value::validated_to_function(ctx, args[1 + (args.count == 3)]);
ValueType session_callback = Value::from_null(ctx);
- if (argc == 3) {
- session_callback = Value::validated_to_function(ctx, arguments[1]);
+ if (args.count == 3) {
+ session_callback = Value::validated_to_function(ctx, args[1]);
}
#if REALM_ENABLE_SYNC
@@ -754,31 +752,33 @@ void RealmClass::wait_for_download_completion(ContextType ctx, FunctionType,
return;
}
}
+#else
+ static_cast(config_object);
#endif
Function::callback(ctx, callback_function, this_object, 0, nullptr);
}
template
-void RealmClass::objects(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
- validate_argument_count(argc, 1);
+void RealmClass::objects(ContextType ctx, FunctionType, ObjectType this_object, Arguments args, ReturnValue &return_value) {
+ args.validate_maximum(1);
SharedRealm realm = *get_internal>(this_object);
std::string object_type;
- validated_object_schema_for_value(ctx, realm, arguments[0], object_type);
+ validated_object_schema_for_value(ctx, realm, args[0], object_type);
return_value.set(ResultsClass::create_instance(ctx, realm, object_type));
}
template
-void RealmClass::object_for_primary_key(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
- validate_argument_count(argc, 2);
+void RealmClass::object_for_primary_key(ContextType ctx, FunctionType, ObjectType this_object, Arguments args, ReturnValue &return_value) {
+ args.validate_maximum(2);
SharedRealm realm = *get_internal>(this_object);
std::string object_type;
- auto &object_schema = validated_object_schema_for_value(ctx, realm, arguments[0], object_type);
+ auto &object_schema = validated_object_schema_for_value(ctx, realm, args[0], object_type);
NativeAccessor accessor(ctx, realm, object_schema);
- auto realm_object = realm::Object::get_for_primary_key(accessor, realm, object_schema, arguments[1]);
+ auto realm_object = realm::Object::get_for_primary_key(accessor, realm, object_schema, args[1]);
if (realm_object.is_valid()) {
return_value.set(RealmObjectClass::create_instance(ctx, std::move(realm_object)));
@@ -789,21 +789,22 @@ void RealmClass::object_for_primary_key(ContextType ctx, FunctionType, Object
}
template
-void RealmClass::create(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
- validate_argument_count(argc, 2, 3);
+void RealmClass::create(ContextType ctx, FunctionType, ObjectType this_object, Arguments args, ReturnValue &return_value) {
+ args.validate_maximum(3);
SharedRealm realm = *get_internal>(this_object);
+ realm->verify_open();
std::string object_type;
- auto &object_schema = validated_object_schema_for_value(ctx, realm, arguments[0], object_type);
+ auto &object_schema = validated_object_schema_for_value(ctx, realm, args[0], object_type);
- ObjectType object = Value::validated_to_object(ctx, arguments[1], "properties");
- if (Value::is_array(ctx, arguments[1])) {
+ ObjectType object = Value::validated_to_object(ctx, args[1], "properties");
+ if (Value::is_array(ctx, args[1])) {
object = Schema::dict_for_property_array(ctx, object_schema, object);
}
bool update = false;
- if (argc == 3) {
- update = Value::validated_to_boolean(ctx, arguments[2], "update");
+ if (args.count == 3) {
+ update = Value::validated_to_boolean(ctx, args[2], "update");
}
NativeAccessor accessor(ctx, realm, object_schema);
@@ -812,15 +813,16 @@ void RealmClass::create(ContextType ctx, FunctionType, ObjectType this_object
}
template
-void RealmClass::delete_one(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
- validate_argument_count(argc, 1);
+void RealmClass::delete_one(ContextType ctx, FunctionType, ObjectType this_object, Arguments args, ReturnValue &return_value) {
+ args.validate_maximum(1);
SharedRealm realm = *get_internal>(this_object);
+ realm->verify_open();
if (!realm->is_in_transaction()) {
throw std::runtime_error("Can only delete objects within a transaction.");
}
- ObjectType arg = Value::validated_to_object(ctx, arguments[0]);
+ ObjectType arg = Value::validated_to_object(ctx, args[0], "object");
if (Object::template is_instance>(ctx, arg)) {
auto object = get_internal>(arg);
@@ -859,10 +861,11 @@ void RealmClass::delete_one(ContextType ctx, FunctionType, ObjectType this_ob
}
template
-void RealmClass::delete_all(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
- validate_argument_count(argc, 0);
+void RealmClass::delete_all(ContextType ctx, FunctionType, ObjectType this_object, Arguments args, ReturnValue &return_value) {
+ args.validate_maximum(0);
SharedRealm realm = *get_internal>(this_object);
+ realm->verify_open();
if (!realm->is_in_transaction()) {
throw std::runtime_error("Can only delete objects within a transaction.");
@@ -874,18 +877,18 @@ void RealmClass::delete_all(ContextType ctx, FunctionType, ObjectType this_ob
}
template
-void RealmClass::write(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
- validate_argument_count(argc, 1);
+void RealmClass::write(ContextType ctx, FunctionType, ObjectType this_object, Arguments args, ReturnValue &return_value) {
+ args.validate_maximum(1);
SharedRealm realm = *get_internal>(this_object);
- FunctionType callback = Value::validated_to_function(ctx, arguments[0]);
+ FunctionType callback = Value::validated_to_function(ctx, args[0]);
realm->begin_transaction();
try {
Function::call(ctx, callback, this_object, 0, nullptr);
}
- catch (std::exception &e) {
+ catch (...) {
realm->cancel_transaction();
throw;
}
@@ -894,82 +897,76 @@ void RealmClass::write(ContextType ctx, FunctionType, ObjectType this_object,
}
template
-void RealmClass::begin_transaction(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
- validate_argument_count(argc, 0);
+void RealmClass::begin_transaction(ContextType ctx, FunctionType, ObjectType this_object, Arguments args, ReturnValue &return_value) {
+ args.validate_maximum(0);
SharedRealm realm = *get_internal>(this_object);
realm->begin_transaction();
}
template
-void RealmClass::commit_transaction(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
- validate_argument_count(argc, 0);
+void RealmClass::commit_transaction(ContextType ctx, FunctionType, ObjectType this_object, Arguments args, ReturnValue &return_value) {
+ args.validate_maximum(0);
SharedRealm realm = *get_internal>(this_object);
realm->commit_transaction();
}
template
-void RealmClass::cancel_transaction(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
- validate_argument_count(argc, 0);
+void RealmClass::cancel_transaction(ContextType ctx, FunctionType, ObjectType this_object, Arguments args, ReturnValue &return_value) {
+ args.validate_maximum(0);
SharedRealm realm = *get_internal>(this_object);
realm->cancel_transaction();
}
template
-void RealmClass::add_listener(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
- validate_argument_count(argc, 2);
+void RealmClass::add_listener(ContextType ctx, FunctionType, ObjectType this_object, Arguments args, ReturnValue &return_value) {
+ args.validate_maximum(2);
- validated_notification_name(ctx, arguments[0]);
- auto callback = Value::validated_to_function(ctx, arguments[1]);
+ validated_notification_name(ctx, args[0]);
+ auto callback = Value::validated_to_function(ctx, args[1]);
SharedRealm realm = *get_internal>(this_object);
- if (realm->is_closed()) {
- throw ClosedRealmException();
- }
+ realm->verify_open();
get_delegate(realm.get())->add_notification(callback);
}
template
-void RealmClass::remove_listener(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
- validate_argument_count(argc, 2);
+void RealmClass::remove_listener(ContextType ctx, FunctionType, ObjectType this_object, Arguments args, ReturnValue &return_value) {
+ args.validate_maximum(2);
- validated_notification_name(ctx, arguments[0]);
- auto callback = Value::validated_to_function(ctx, arguments[1]);
+ validated_notification_name(ctx, args[0]);
+ auto callback = Value::validated_to_function(ctx, args[1]);
SharedRealm realm = *get_internal>(this_object);
- if (realm->is_closed()) {
- throw ClosedRealmException();
- }
+ realm->verify_open();
get_delegate(realm.get())->remove_notification(callback);
}
template
-void RealmClass::remove_all_listeners(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
- validate_argument_count(argc, 0, 1);
- if (argc) {
- validated_notification_name(ctx, arguments[0]);
+void RealmClass::remove_all_listeners(ContextType ctx, FunctionType, ObjectType this_object, Arguments args, ReturnValue &return_value) {
+ args.validate_maximum(1);
+ if (args.count) {
+ validated_notification_name(ctx, args[0]);
}
SharedRealm realm = *get_internal>(this_object);
- if (realm->is_closed()) {
- throw ClosedRealmException();
- }
+ realm->verify_open();
get_delegate(realm.get())->remove_all_notifications();
}
template
-void RealmClass::close(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
- validate_argument_count(argc, 0);
+void RealmClass::close(ContextType ctx, FunctionType, ObjectType this_object, Arguments args, ReturnValue &return_value) {
+ args.validate_maximum(0);
SharedRealm realm = *get_internal>(this_object);
realm->close();
}
template
-void RealmClass::compact(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
- validate_argument_count(argc, 0);
+void RealmClass::compact(ContextType ctx, FunctionType, ObjectType this_object, Arguments args, ReturnValue &return_value) {
+ args.validate_maximum(0);
SharedRealm realm = *get_internal>(this_object);
if (realm->is_in_transaction()) {
diff --git a/src/js_schema.hpp b/src/js_schema.hpp
index e96e0290..51ef3aa5 100644
--- a/src/js_schema.hpp
+++ b/src/js_schema.hpp
@@ -180,9 +180,9 @@ ObjectSchema Schema::parse_object_schema(ContextType ctx, ObjectType object_s
ObjectDefaults object_defaults;
ObjectSchema object_schema;
- object_schema.name = Object::validated_get_string(ctx, object_schema_object, name_string);
+ object_schema.name = Object::validated_get_string(ctx, object_schema_object, name_string, "ObjectSchema");
- ObjectType properties_object = Object::validated_get_object(ctx, object_schema_object, properties_string, "ObjectSchema must have a 'properties' object.");
+ ObjectType properties_object = Object::validated_get_object(ctx, object_schema_object, properties_string, "ObjectSchema");
if (Value::is_array(ctx, properties_object)) {
uint32_t length = Object::validated_get_length(ctx, properties_object);
for (uint32_t i = 0; i < length; i++) {
@@ -233,7 +233,8 @@ ObjectSchema Schema::parse_object_schema(ContextType ctx, ObjectType object_s
}
template
-realm::Schema Schema::parse_schema(ContextType ctx, ObjectType schema_object, ObjectDefaultsMap &defaults, ConstructorMap &constructors) {
+realm::Schema Schema::parse_schema(ContextType ctx, ObjectType schema_object,
+ ObjectDefaultsMap &defaults, ConstructorMap &constructors) {
std::vector schema;
uint32_t length = Object::validated_get_length(ctx, schema_object);
diff --git a/src/js_sync.hpp b/src/js_sync.hpp
index 0ff96000..5d7c1d72 100644
--- a/src/js_sync.hpp
+++ b/src/js_sync.hpp
@@ -22,6 +22,8 @@
#include