Merge pull request #658 from realm/al-sync

Node and fine grained notification support
This commit is contained in:
Ari Lazier 2016-11-15 11:00:08 -08:00 committed by GitHub
commit 7a4bf0e5ec
104 changed files with 4031 additions and 935 deletions

7
.dir-locals.el Normal file
View File

@ -0,0 +1,7 @@
;; Project specific Emacs settings
((nil . ((c-basic-offset . 4)
(indent-tabs-mode . nil)
(fill-column . 80)
(c-file-style . "ellemtel")
(c-file-offsets . ((innamespace . 0)))
(show-trailing-whitespace . t))))

View File

@ -7,3 +7,4 @@ node_modules/
vendor/ vendor/
/tests/test-runners/ /tests/test-runners/
/object-server-for-testing/

View File

@ -1,10 +1,19 @@
{ {
"root": true, "root": true,
"env": {
"es6": true,
"node": true
},
"extends": "eslint:recommended", "extends": "eslint:recommended",
"rules": { "rules": {
"comma-dangle": 0, "comma-dangle": 0,
"no-empty": 0, "no-empty": 0,
"no-unused-vars": 1, "no-unused-vars": [
"warn", {
"varsIgnorePattern": "^_",
"argsIgnorePattern": "^_"
}
],
"strict": [2, "global"] "strict": [2, "global"]
} }
} }

12
.gitignore vendored
View File

@ -18,6 +18,10 @@
# core # core
core core
core-* core-*
sync
sync-*
node-sync
node-sync-*
# sh build.sh config # sh build.sh config
/Realm/config.mk /Realm/config.mk
@ -98,6 +102,8 @@ build/
# node.js # node.js
node_modules/ node_modules/
npm-debug.log npm-debug.log
/compiled/
*.lock
# Android/IJ # Android/IJ
/android/ /android/
@ -108,3 +114,9 @@ local.properties
# Visual Studio Code # Visual Studio Code
.vscode .vscode
tsconfig.json tsconfig.json
# Tests
object-server-for-testing/
tests/realm-object-server/
vendor/sync
vendor/sync*

View File

@ -1,10 +1,11 @@
x.x.x Release notes (yyyy-MM-dd) 0.15.0 Release notes (2016-11-15)
============================================================= =============================================================
### Breaking changes ### Breaking changes
* None * None
### Enhancements ### Enhancements
* None * Support for fine grained notifications
* Updated test and examples for react-natve v0.37.0
### Bugfixes ### Bugfixes
* None * None

View File

@ -1,37 +1,8 @@
FROM node:6 FROM ubuntu:xenial
# Make debugging quicker. RUN apt-get update && \
RUN apt-get update && apt-get install -y gdb vim apt-get install -y curl && \
curl -sL https://deb.nodesource.com/setup_4.x | bash - && \
apt-get install -y nodejs gcc-4.9 python build-essential
# Add non-root user. ENV NPM_CONFIG_UNSAFE_PERM true
RUN useradd -ms /bin/bash user
# Make our workspace directory and work from there.
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Get the node_modules setup before anything else.
COPY package.json .
RUN npm install
# Make sure core is downloaded.
COPY scripts/download-core.sh scripts/
RUN scripts/download-core.sh node
# Copy only what we need to build.
COPY src/ src/
# Build the Debug version of the module.
RUN src/node/build-node.sh Debug
# Copy everything else needed to run tests.
COPY lib/ lib/
COPY scripts/ scripts/
COPY tests/ tests/
# Switch to the non-root user.
RUN chown -R user .
USER user
# Default to running the Node tests
CMD ["node", "tests"]

View File

@ -41,7 +41,7 @@ Prerequisites:
First clone this repository: First clone this repository:
``` ```
git clone https://github.com/realm/realm-js.git git clone https://github.com/realm/realm-js-private.git
``` ```
Then in the cloned directory: Then in the cloned directory:
@ -60,6 +60,15 @@ To build for Android:
- `./gradlew publishAndroid` - `./gradlew publishAndroid`
- The compiled version of the Android module is here: `<project-root>/android` - The compiled version of the Android module is here: `<project-root>/android`
To build for Node:
- `REALM_CORE_PREFIX=/path/to/realm-core REALM_SYNC_PREFIX=/path/to/realm-sync npm install`
The `REALM_*_PREFIX` paths need to be absolute. Make sure to run `sh build.sh build-node` in both core and sync. Optionally export `REALMJS_USE_DEBUG_CORE=true` to link against the debug version of the realm binaries.
To build the Developer Edition of the module, pass `--developer_edition` to `npm install` or change the default value in `binding.gyp`.
`node-pre-gyp` is used for packaging. Run `scripts/build-node-pre-gyp.sh` with the same arguments and environment variables as `npm install` on all platforms (e.g. Linux and Darwin). Then, edit `package.json` to remove the `--build-from-source` option from the install script and run `npm pack`. Lastly, either create a fat package by merging all the tarballs created so far into one, or upload the `node-pre-gyp` tarballs to the CDN the `binary` section of `package.json` points to.
## Code of Conduct ## Code of Conduct
This project adheres to the Contributor Covenant [code of conduct](https://realm.io/conduct/). This project adheres to the Contributor Covenant [code of conduct](https://realm.io/conduct/).

View File

@ -5,12 +5,14 @@
}, },
"DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : {
"40F53A12E4AE40C654358321B91166ABD3E910A6" : 0, "40F53A12E4AE40C654358321B91166ABD3E910A6" : 0,
"F6F96CA34C5878B0A9123C7C37855491A5E599DA" : 0 "F6F96CA34C5878B0A9123C7C37855491A5E599DA" : 0,
"8F3C415DA79CDA7D23734F285B95F9F9A3C0CB81" : 0
}, },
"DVTSourceControlWorkspaceBlueprintIdentifierKey" : "5EE721F9-041C-4877-9E73-A925C9DB080A", "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "5EE721F9-041C-4877-9E73-A925C9DB080A",
"DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
"40F53A12E4AE40C654358321B91166ABD3E910A6" : "realm-js\/", "40F53A12E4AE40C654358321B91166ABD3E910A6" : "realm-js\/",
"F6F96CA34C5878B0A9123C7C37855491A5E599DA" : "realm-js\/vendor\/GCDWebServer\/" "F6F96CA34C5878B0A9123C7C37855491A5E599DA" : "realm-js\/vendor\/GCDWebServer\/",
"8F3C415DA79CDA7D23734F285B95F9F9A3C0CB81" : "realm-js\/src\/object-store\/"
}, },
"DVTSourceControlWorkspaceBlueprintNameKey" : "Realm", "DVTSourceControlWorkspaceBlueprintNameKey" : "Realm",
"DVTSourceControlWorkspaceBlueprintVersion" : 204, "DVTSourceControlWorkspaceBlueprintVersion" : 204,
@ -21,6 +23,11 @@
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "40F53A12E4AE40C654358321B91166ABD3E910A6" "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "40F53A12E4AE40C654358321B91166ABD3E910A6"
}, },
{
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/realm\/realm-object-store.git",
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "8F3C415DA79CDA7D23734F285B95F9F9A3C0CB81"
},
{ {
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/swisspol\/GCDWebServer.git", "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/swisspol\/GCDWebServer.git",
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",

122
binding.gyp Normal file
View File

@ -0,0 +1,122 @@
{
"variables": {
"realm_node_build_as_library%": "0",
"realm_download_binaries%": "1"
},
"includes": [
"src/node/gyp/target_defaults.gypi",
"src/node/gyp/realm.gyp"
],
"targets": [
{
"target_name": "realm",
"dependencies": [
"object-store"
],
"sources": [
"src/node/platform.cpp",
"src/js_realm.cpp"
],
"include_dirs": [
"src"
],
"conditions": [
["realm_node_build_as_library", {
"type": "static_library",
"export_dependent_settings": [ "object-store" ]
}, {
"sources": [
"src/node/node_init.cpp"
]
}]
]
},
{
"target_name": "object-store",
"dependencies": [ "realm-core" ],
"type": "static_library",
"include_dirs": [
"src/object-store/src",
"src/object-store/src/impl",
"src/object-store/src/impl/apple",
"src/object-store/src/parser",
"src/object-store/external/pegtl"
],
"sources": [
"src/object-store/src/collection_notifications.cpp",
"src/object-store/src/index_set.cpp",
"src/object-store/src/list.cpp",
"src/object-store/src/object_schema.cpp",
"src/object-store/src/object_store.cpp",
"src/object-store/src/results.cpp",
"src/object-store/src/schema.cpp",
"src/object-store/src/shared_realm.cpp",
"src/object-store/src/thread_confined.cpp",
"src/object-store/src/impl/collection_change_builder.cpp",
"src/object-store/src/impl/collection_notifier.cpp",
"src/object-store/src/impl/handover.cpp",
"src/object-store/src/impl/list_notifier.cpp",
"src/object-store/src/impl/realm_coordinator.cpp",
"src/object-store/src/impl/results_notifier.cpp",
"src/object-store/src/impl/transact_log_handler.cpp",
"src/object-store/src/impl/weak_realm_notifier.cpp",
"src/object-store/src/parser/parser.cpp",
"src/object-store/src/parser/query_builder.cpp",
"src/object-store/src/util/format.cpp",
"src/object-store/src/util/thread_id.cpp",
],
"conditions": [
["OS=='linux'", {
"sources": [
"src/object-store/src/impl/android/external_commit_helper.cpp",
]
}],
["OS=='mac'", {
"sources": [
"src/object-store/src/impl/apple/external_commit_helper.cpp",
"src/object-store/src/impl/apple/keychain_helper.cpp"
]
}],
["realm_enable_sync", {
"dependencies": [ "realm-sync" ],
"sources": [
"src/object-store/src/sync/sync_manager.cpp",
"src/object-store/src/sync/sync_user.cpp",
"src/object-store/src/sync/sync_session.cpp",
"src/object-store/src/sync/impl/sync_file.cpp",
"src/object-store/src/sync/impl/sync_metadata.cpp"
],
}]
],
"all_dependent_settings": {
"include_dirs": [
"src/object-store/src",
"src/object-store/src/impl",
"src/object-store/src/impl/apple",
"src/object-store/src/parser",
"src/object-store/external/pegtl"
]
},
"export_dependent_settings": [
"<@(_dependencies)" # re-export settings related to linking the realm binaries
]
}
],
"conditions": [
["not realm_node_build_as_library", {
"targets": [
{
"target_name": "action_after_build",
"type": "none",
"dependencies": [ "<(module_name)" ],
"copies": [
{
"files": [ "<(PRODUCT_DIR)/<(module_name).node" ],
"destination": "<(module_path)"
}
]
}
]
}]
]
}

5
dependencies.list Normal file
View File

@ -0,0 +1,5 @@
PACKAGE_NAME=realm-js
VERSION=0.14.3-6
REALM_CORE_VERSION=2.1.4
REALM_SYNC_VERSION=1.0.0-BETA-3.3
REALM_OBJECT_SERVER_VERSION=1.0.0-BETA-2.1

View File

@ -259,6 +259,39 @@ class Collection {
* @since 0.11.0 * @since 0.11.0
*/ */
reduceRight(callback, initialValue) {} reduceRight(callback, initialValue) {}
/**
* Add a listener `callback` which will be called when a **live** collection instance changes.
* @param {function(collection, changes)} callback - A function to be called when changes occur.
* The callback function is called with two arguments:
* - `collection`: the collection instance that changed,
* - `changes`: a dictionary with keys `insertions`, `modifications` and `deletions`,
* each containing a list of indices that were inserted, updated or deleted respectively.
* @throws {Error} If `callback` is not a function.
* @example
* wines.addListener((collection, changes) => {
* // collection === wines
* console.log(`${changes.insertions.length} insertions`);
* console.log(`${changes.modifications.length} modifications`);
* console.log(`${changes.deletions.length} deletions`);
* console.log(`new size of collection: ${collection.length}`);
* });
*/
addListener(callback) {}
/**
* Remove the listener `callback` from the collection instance.
* @param {function(collection, changes)} callback - Callback function that was previously
* added as a listener through the {@link Collection#addListener addListener} method.
* @throws {Error} If `callback` is not a function.
*/
removeListener(callback) {}
/**
* Remove all `callback` listeners from the collection instance.
*/
removeAllListeners(name) {}
} }
/** /**

View File

@ -7,7 +7,7 @@
}, },
"source": { "source": {
"include": ["docs"], "include": ["docs"],
"exclude": ["docs/jsdoc-template", "docs/output"] "exclude": ["docs/jsdoc-template", "docs/output", "docs/sync.js"]
}, },
"tags": { "tags": {
"allowUnknownTags": false "allowUnknownTags": false

View File

@ -189,6 +189,10 @@ Realm.defaultPath;
* object types in this Realm. **Required** when first creating a Realm at this `path`. * object types in this Realm. **Required** when first creating a Realm at this `path`.
* @property {number} [schemaVersion] - **Required** (and must be incremented) after * @property {number} [schemaVersion] - **Required** (and must be incremented) after
* changing the `schema`. * changing the `schema`.
* @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
*/ */
/** /**

View File

@ -20,7 +20,9 @@
* Instances of this class are typically **live** collections returned by * Instances of this class are typically **live** collections returned by
* {@link Realm#objects objects()} that will update as new objects are either * {@link Realm#objects objects()} that will update as new objects are either
* added to or deleted from the Realm that match the underlying query. Results returned by * added to or deleted from the Realm that match the underlying query. Results returned by
* {@link Realm.Results#snapshot snapshot()}, however, are will **not** live update. * {@link Realm.Results#snapshot snapshot()}, however, will **not** live update
* (and listener callbacks added through {@link Realm.Results#addListener addListener()}
* will thus never be called).
* @extends Realm.Collection * @extends Realm.Collection
* @memberof Realm * @memberof Realm
*/ */

129
docs/sync.js Normal file
View File

@ -0,0 +1,129 @@
////////////////////////////////////////////////////////////////////////////
//
// 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.
//
////////////////////////////////////////////////////////////////////////////
/**
* @memberof Realm
*/
class Sync {
/**
* Set a global listener function.
* @param {string} local_path - The path to the directory where realm files are stored [deprecated]
* @param {string} server_url - The sync server to listen to
* @param {SyncUser} admin_user - An admin user obtained by calling `new Realm.Sync.User.Admin`
* @param {function(realm_name)} filter_callback - Return true to recieve changes for the given realm
* @param {function(realm_name, realm, change_set)} change_callback - called on any realm changes with
* the following arguments:
* - `realm_name` - path of the Realm on which changes occurred
* - `realm` - a `Realm` object for the changed Realm
* - `change_set` - a dictionary of object names to arays of indexes indicating the indexes of objects of each type
* which have been added, removed, or modified
*/
static setGlobalListener(local_path, server_url, admin_user, filter_callback, change_callback) {}
/**
* Set the sync log level.
* @param {string} log_level
*/
static setLogLevel(log_level) {}
}
/**
* @typedef Realm.Sync~LogLevel
* @type {("error"|"info"|"debug")}
*/
/**
* Class that describes authentication errors in the Realm Object Server
* @memberof Realm.Sync
*/
class AuthError extends Error {
/**
* The numerical code for this error.
* @type {number}
*/
get code() {}
/**
* The unique help URI that describes this error.
* @type {string}
*/
get type() {}
}
/**
* Class for logging in and managing Sync users.
* @memberof Realm.Sync
*/
class User {
/**
* Login a sync user with username and password.
* @param {string} server - authentication server
* @param {string} username
* @param {string} password
* @param {function(error, user)} callback - called with the following arguments:
* - `error` - an Error object is provided on failure
* - `user` - a valid User object on success
*/
login(server, username, password, callback) {}
/**
* Login a sync user using an external login provider.
* @param {string} server - authentication server
* @param {string} provider - The provider type
* @param {string} providerToken - The access token for the given provider
* @param {function(error, User)} callback - called with the following arguments:
* - `error` - an Error object is provided on failure
* - `user` - a valid User object on success
*/
loginWithProvider(server, provider, providerToken, callback) {}
/**
* Create a new user using the username/password provider
* @param {string} server - authentication server
* @param {string} username
* @param {string} password
* @param {function(error, User)} callback - called with the following arguments:
* - `error` - an Error object is provided on failure
* - `user` - a valid User object on success
*/
create(server, username, password, callback) {}
/**
* Create an admin user for the given authentication server with an existing token
* @param {string} server - authentication server
* @param {string} adminToken - existing admin token
* @return {User} - admin user populated with the given token and server
*/
adminUser(server, adminToken) {}
/**
* A dictionary containing users that are currently logged in.
* The keys in the dictionary are user identities, values are corresponding User objects.
* @type {object}
*/
get all() {}
/**
* Get the currently logged in user.
* Throws error if > 1 user logged in, returns undefined if no users logged in.
* @type {User}
*/
get current() {}
}

View File

@ -7,7 +7,8 @@
android:allowBackup="true" android:allowBackup="true"
android:label="@string/app_name" android:label="@string/app_name"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:theme="@style/AppTheme"> android:theme="@style/AppTheme"
android:name=".MainApplication">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:label="@string/app_name" android:label="@string/app_name"

View File

@ -1,13 +1,6 @@
package io.realm.react.example; package io.realm.react.example;
import com.facebook.react.ReactActivity; import com.facebook.react.ReactActivity;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import java.util.Arrays;
import java.util.List;
import io.realm.react.RealmReactPackage;
public class MainActivity extends ReactActivity { public class MainActivity extends ReactActivity {
@ -20,24 +13,4 @@ public class MainActivity extends ReactActivity {
return "ReactExample"; return "ReactExample";
} }
/**
* Returns whether dev mode should be enabled.
* This enables e.g. the dev menu.
*/
@Override
protected boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
/**
* A list of packages used by the app. If the app uses additional views
* or modules besides the default ones, add more packages here.
*/
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new RealmReactPackage()
);
}
} }

View File

@ -0,0 +1,40 @@
package io.realm.react.example;
import android.app.Application;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import java.util.Arrays;
import java.util.List;
import io.realm.react.RealmReactPackage;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
protected boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new RealmReactPackage()
);
}
};
/**
* A list of packages used by the app. If the app uses additional views
* or modules besides the default ones, add more packages here.
*/
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
}

View File

@ -5,7 +5,7 @@ buildscript {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:1.3.1' classpath 'com.android.tools.build:gradle:2.2.2'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files

View File

@ -1,5 +1,6 @@
#Fri Nov 11 18:15:12 GMT 2016
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip

View File

@ -34,6 +34,7 @@ TodoList.schema = {
name: 'TodoList', name: 'TodoList',
properties: { properties: {
name: 'string', name: 'string',
creationDate: 'date',
items: {type: 'list', objectType: 'Todo'}, items: {type: 'list', objectType: 'Todo'},
}, },
}; };

View File

@ -38,15 +38,18 @@ export default class TodoApp extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
let todoLists = realm.objects('TodoList'); // This is a Results object, which will live-update.
if (todoLists.length < 1) { this.todoLists = realm.objects('TodoList').sorted('creationDate');
if (this.todoLists.length < 1) {
realm.write(() => { realm.write(() => {
realm.create('TodoList', {name: 'Todo List'}); realm.create('TodoList', {name: 'Todo List', creationDate: new Date()});
}); });
} }
this.todoLists.addListener((name, changes) => {
console.log("changed: " + JSON.stringify(changes));
});
console.log("registered listener");
// This is a Results object, which will live-update.
this.todoLists = todoLists;
// Bind all the methods that we will be passing as props. // Bind all the methods that we will be passing as props.
this.renderScene = this.renderScene.bind(this); this.renderScene = this.renderScene.bind(this);
@ -79,7 +82,6 @@ export default class TodoApp extends React.Component {
component: TodoListView, component: TodoListView,
passProps: { passProps: {
ref: 'listView', ref: 'listView',
items: this.todoLists,
extraItems: extraItems, extraItems: extraItems,
onPressItem: this._onPressTodoList, onPressItem: this._onPressTodoList,
}, },
@ -105,7 +107,8 @@ export default class TodoApp extends React.Component {
} }
renderScene(route) { renderScene(route) {
return <route.component {...route.passProps} /> console.log(this.todoLists);
return <route.component items={this.todoLists} {...route.passProps} />
} }
_addNewTodoItem(list) { _addNewTodoItem(list) {
@ -128,7 +131,7 @@ export default class TodoApp extends React.Component {
} }
realm.write(() => { realm.write(() => {
realm.create('TodoList', {name: ''}); realm.create('TodoList', {name: '', creationDate: new Date()});
}); });
this._setEditingRow(items.length - 1); this._setEditingRow(items.length - 1);

View File

@ -71,6 +71,55 @@
remoteGlobalIDString = 13B07F861A680F5B00A75B9A; remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
remoteInfo = ReactExample; remoteInfo = ReactExample;
}; };
02F8FE011DD6B23100BD85F8 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 2D2A283A1D9B042B00D4039D;
remoteInfo = "RCTImage-tvOS";
};
02F8FE051DD6B23100BD85F8 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 2D2A28471D9B043800D4039D;
remoteInfo = "RCTLinking-tvOS";
};
02F8FE091DD6B23100BD85F8 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 2D2A28541D9B044C00D4039D;
remoteInfo = "RCTNetwork-tvOS";
};
02F8FE0D1DD6B23100BD85F8 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 2D2A28611D9B046600D4039D;
remoteInfo = "RCTSettings-tvOS";
};
02F8FE111DD6B23100BD85F8 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 2D2A287B1D9B048500D4039D;
remoteInfo = "RCTText-tvOS";
};
02F8FE161DD6B23100BD85F8 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 2D2A28881D9B049200D4039D;
remoteInfo = "RCTWebSocket-tvOS";
};
02F8FE191DD6B23100BD85F8 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 2D2A28131D9B038B00D4039D;
remoteInfo = "React-tvOS";
};
139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = { 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy; isa = PBXContainerItemProxy;
containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;
@ -214,6 +263,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
00C302C01ABCB91800DB3ED1 /* libRCTImage.a */, 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */,
02F8FE021DD6B23100BD85F8 /* libRCTImage-tvOS.a */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@ -222,6 +272,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */, 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */,
02F8FE0A1DD6B23100BD85F8 /* libRCTNetwork-tvOS.a */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@ -249,6 +300,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
139105C11AF99BAD00B5F7CC /* libRCTSettings.a */, 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */,
02F8FE0E1DD6B23100BD85F8 /* libRCTSettings-tvOS.a */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@ -257,6 +309,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
139FDEF41B06529B00C62182 /* libRCTWebSocket.a */, 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */,
02F8FE171DD6B23100BD85F8 /* libRCTWebSocket-tvOS.a */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@ -278,6 +331,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
146834041AC3E56700842450 /* libReact.a */, 146834041AC3E56700842450 /* libReact.a */,
02F8FE1A1DD6B23100BD85F8 /* libReact-tvOS.a */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@ -286,6 +340,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
78C398B91ACF4ADC00677621 /* libRCTLinking.a */, 78C398B91ACF4ADC00677621 /* libRCTLinking.a */,
02F8FE061DD6B23100BD85F8 /* libRCTLinking-tvOS.a */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@ -314,6 +369,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
832341B51AAA6A8300B99B32 /* libRCTText.a */, 832341B51AAA6A8300B99B32 /* libRCTText.a */,
02F8FE121DD6B23100BD85F8 /* libRCTText-tvOS.a */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@ -505,6 +561,55 @@
remoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */; remoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR; sourceTree = BUILT_PRODUCTS_DIR;
}; };
02F8FE021DD6B23100BD85F8 /* libRCTImage-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libRCTImage-tvOS.a";
remoteRef = 02F8FE011DD6B23100BD85F8 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
02F8FE061DD6B23100BD85F8 /* libRCTLinking-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libRCTLinking-tvOS.a";
remoteRef = 02F8FE051DD6B23100BD85F8 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
02F8FE0A1DD6B23100BD85F8 /* libRCTNetwork-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libRCTNetwork-tvOS.a";
remoteRef = 02F8FE091DD6B23100BD85F8 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
02F8FE0E1DD6B23100BD85F8 /* libRCTSettings-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libRCTSettings-tvOS.a";
remoteRef = 02F8FE0D1DD6B23100BD85F8 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
02F8FE121DD6B23100BD85F8 /* libRCTText-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libRCTText-tvOS.a";
remoteRef = 02F8FE111DD6B23100BD85F8 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
02F8FE171DD6B23100BD85F8 /* libRCTWebSocket-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libRCTWebSocket-tvOS.a";
remoteRef = 02F8FE161DD6B23100BD85F8 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
02F8FE1A1DD6B23100BD85F8 /* libReact-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libReact-tvOS.a";
remoteRef = 02F8FE191DD6B23100BD85F8 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
139105C11AF99BAD00B5F7CC /* libRCTSettings.a */ = { 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */ = {
isa = PBXReferenceProxy; isa = PBXReferenceProxy;
fileType = archive.ar; fileType = archive.ar;
@ -684,6 +789,8 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CC = "$(SRCROOT)/../../../scripts/ccache-clang.sh";
CXX = "$(SRCROOT)/../../../scripts/ccache-clang++.sh";
DEAD_CODE_STRIPPING = NO; DEAD_CODE_STRIPPING = NO;
HEADER_SEARCH_PATHS = ( HEADER_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@ -701,6 +808,8 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CC = "$(SRCROOT)/../../../scripts/ccache-clang.sh";
CXX = "$(SRCROOT)/../../../scripts/ccache-clang++.sh";
HEADER_SEARCH_PATHS = ( HEADER_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
@ -717,6 +826,7 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
CC = "$(SRCROOT)/../../../scripts/ccache-clang.sh";
CLANG_CXX_LANGUAGE_STANDARD = "c++14"; CLANG_CXX_LANGUAGE_STANDARD = "c++14";
CLANG_CXX_LIBRARY = "libc++"; CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
@ -732,6 +842,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CXX = "$(SRCROOT)/../../../scripts/ccache-clang++.sh";
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO; GCC_DYNAMIC_NO_PIC = NO;
@ -764,6 +875,7 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
CC = "$(SRCROOT)/../../../scripts/ccache-clang.sh";
CLANG_CXX_LANGUAGE_STANDARD = "c++14"; CLANG_CXX_LANGUAGE_STANDARD = "c++14";
CLANG_CXX_LIBRARY = "libc++"; CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
@ -779,6 +891,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES; COPY_PHASE_STRIP = YES;
CXX = "$(SRCROOT)/../../../scripts/ccache-clang++.sh";
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;

View File

@ -6,8 +6,8 @@
"start": "react-native start" "start": "react-native start"
}, },
"dependencies": { "dependencies": {
"react": "~15.2.0", "react": "15.3.2",
"react-native": "^0.31.0", "react-native": "^0.37.0",
"realm": "file:../.." "realm": "file:../.."
} }
} }

View File

@ -1,5 +1,2 @@
{ {
"env": {
"commonjs": true
}
} }

View File

@ -1,7 +1,7 @@
{ {
"env": { "env": {
"es6": true, "worker": true,
"worker": true "node": false
}, },
"globals": { "globals": {
"global": true "global": true

View File

@ -52,7 +52,7 @@ export function fireMutationListeners(realmId) {
} }
} }
export function createCollection(prototype, realmId, info, mutable) { export function createCollection(prototype, realmId, info, _mutable) {
let collection = Object.create(prototype); let collection = Object.create(prototype);
let size; let size;

View File

@ -145,7 +145,7 @@ Object.defineProperties(Realm, {
set: util.setterForProperty('defaultPath'), set: util.setterForProperty('defaultPath'),
}, },
schemaVersion: { schemaVersion: {
value: function(path, encryptionKey) { value: function(_path, _encryptionKey) {
return rpc.callMethod(undefined, Realm[keys.id], 'schemaVersion', Array.from(arguments)); return rpc.callMethod(undefined, Realm[keys.id], 'schemaVersion', Array.from(arguments));
} }
}, },

View File

@ -21,7 +21,7 @@
import * as base64 from './base64'; import * as base64 from './base64';
import { keys, objectTypes } from './constants'; import { keys, objectTypes } from './constants';
const {id: idKey, realm: realmKey} = keys; const {id: idKey, realm: _realmKey} = keys;
const registeredCallbacks = []; const registeredCallbacks = [];
const typeConverters = {}; const typeConverters = {};

28
lib/errors.js Normal file
View File

@ -0,0 +1,28 @@
////////////////////////////////////////////////////////////////////////////
//
// 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.
//
////////////////////////////////////////////////////////////////////////////
'use strict';
class AuthError extends Error {
constructor(problem) {
super(problem.title);
Object.assign(this, problem);
}
}
exports['AuthError'] = AuthError;

67
lib/extensions.js Normal file
View File

@ -0,0 +1,67 @@
////////////////////////////////////////////////////////////////////////////
//
// 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.
//
////////////////////////////////////////////////////////////////////////////
'use strict';
module.exports = function(realmConstructor) {
// Add the specified Array methods to the Collection prototype.
Object.defineProperties(realmConstructor.Collection.prototype, require('./collection-methods'));
// Add sync methods
if (realmConstructor.Sync) {
Object.defineProperties(realmConstructor.Sync.User, require('./user-methods')(realmConstructor));
realmConstructor.Sync.AuthError = require('./errors').AuthError;
if (realmConstructor.Sync.cleanup) {
// FIXME: DOES THIS WORK ON BOTH NODE AND REACT NATIVE?
process.on('exit', realmConstructor.Sync.cleanup);
}
}
// TODO: Remove this now useless object.
var types = Object.freeze({
'BOOL': 'bool',
'INT': 'int',
'FLOAT': 'float',
'DOUBLE': 'double',
'STRING': 'string',
'DATE': 'date',
'DATA': 'data',
'OBJECT': 'object',
'LIST': 'list',
});
Object.defineProperty(realmConstructor, 'Types', {
get: function() {
if (typeof console != 'undefined') {
/* global console */
/* eslint-disable no-console */
var stack = new Error().stack.split("\n").slice(2).join("\n");
var msg = '`Realm.Types` is deprecated! Please specify the type name as lowercase string instead!\n'+stack;
if (console.warn != undefined) {
console.warn(msg);
}
else {
console.log(msg);
}
/* eslint-enable no-console */
}
return types;
},
configurable: true
});
}

View File

@ -18,7 +18,10 @@
'use strict'; 'use strict';
var arrayMethods = require('./collection-methods'); function node_require(module) {
return require(module);
}
var realmConstructor; var realmConstructor;
if (typeof Realm != 'undefined') { if (typeof Realm != 'undefined') {
@ -30,46 +33,16 @@ if (typeof Realm != 'undefined') {
realmConstructor = require('./browser').default; // (exported as ES6 module) realmConstructor = require('./browser').default; // (exported as ES6 module)
// eslint-disable-next-line // eslint-disable-next-line
} else if (typeof process == 'object' && (('' + process) == '[object process]' || typeof jest == 'object')) { } else if (typeof process == 'object' && (('' + process) == '[object process]' || typeof jest == 'object')) {
// If process is defined, we're running in node.
// Prevent React Native packager from seeing this module. // Prevent React Native packager from seeing this module.
var bindings = 'bindings'; var binary = node_require('node-pre-gyp');
realmConstructor = require(bindings)('realm').Realm; var path = node_require('path');
var binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json')));
realmConstructor = require(binding_path).Realm;
} else { } else {
throw new Error('Missing Realm constructor - please ensure RealmReact framework is included!'); throw new Error('Missing Realm constructor - please ensure RealmReact framework is included!');
} }
// Add the specified Array methods to the Collection prototype. require('./extensions')(realmConstructor);
Object.defineProperties(realmConstructor.Collection.prototype, arrayMethods);
// TODO: Remove this now useless object.
var types = Object.freeze({
'BOOL': 'bool',
'INT': 'int',
'FLOAT': 'float',
'DOUBLE': 'double',
'STRING': 'string',
'DATE': 'date',
'DATA': 'data',
'OBJECT': 'object',
'LIST': 'list',
});
Object.defineProperty(realmConstructor, 'Types', {
get: function() {
if (typeof console != 'undefined') {
/* global console */
/* eslint-disable no-console */
var stack = new Error().stack.split("\n").slice(2).join("\n");
var msg = '`Realm.Types` is deprecated! Please specify the type name as lowercase string instead!\n'+stack;
if (console.warn != undefined) {
console.warn(msg);
}
else {
console.log(msg);
}
/* eslint-enable no-console */
}
return types;
},
configurable: true
});
module.exports = realmConstructor; module.exports = realmConstructor;

144
lib/user-methods.js Normal file
View File

@ -0,0 +1,144 @@
'use strict';
const AuthError = require('./errors').AuthError;
function node_require(module) {
return require(module);
}
var post;
if (typeof fetch !== 'undefined') {
post = function(options, callback) {
options.method = 'POST';
// eslint-disable-next-line no-undef
fetch(options.url, options)
.then((response) => {
if (response.status != 200) {
callback(undefined, {statusCode: response.status});
}
else {
return response.text();
}
})
.then((body) => {
callback(undefined, {statusCode: 200}, JSON.parse(body));
})
.catch((error) => {
callback(error);
});
}
}
else {
post = function(options, callback) {
node_require('needle').post(options.url, options.body, options, callback);
}
}
const url_parse = require("url-parse");
const postHeaders = {
'content-type': 'application/json;charset=utf-8',
'accept': 'application/json'
};
function auth_url(server) {
if (server.charAt(server.length-1) != '/') {
return server + '/auth';
}
return server + 'auth';
}
module.exports = function(realmConstructor) {
function _authenticate(server, json, callback) {
json.app_id = '';
var options = {
url: auth_url(server),
body: JSON.stringify(json),
headers: postHeaders,
open_timeout: 5000
};
post(options, function(error, response, body) {
if (error) {
callback(error);
}
else if (response.statusCode != 200) {
callback(new AuthError(JSON.parse(body)));
}
else {
// TODO: validate JSON
const token = body.refresh_token.token;
const identity = body.refresh_token.token_data.identity;
callback(undefined, realmConstructor.Sync.User.createUser(server, identity, token, false));
}
});
}
var methods = {};
methods['adminUser'] = function(token) {
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
var user = realmConstructor.Sync.User.createUser('', uuid, token, true);
return user;
}
methods['register'] = function(server, username, password, callback) {
_authenticate(server, {
provider: 'password',
user_info: { password: password, register: true },
data: username
}, callback);
}
methods['login'] = function(server, username, password, callback) {
_authenticate(server, {
provider: 'password',
user_info: { password: password },
data: username
}, callback);
}
methods['registerWithProvider'] = function(server, provider, providerToken, callback) {
_authenticate(server, {
provider: provider,
data: providerToken
}, callback);
}
methods['_authenticateRealm'] = function(fileUrl, realmUrl, callback) {
var options = {
url: auth_url(this.server),
body: JSON.stringify({
data: this.token,
path: url_parse(realmUrl).pathname,
provider: 'realm',
app_id: ''
}),
headers: postHeaders
};
post(options, function(error, response, body) {
if (error) {
callback(error);
}
else if (response.statusCode != 200) {
callback(new AuthError('Bad response: ' + response.statusCode));
}
else {
// TODO: validate JSON
callback(undefined, {
token: body.access_token.token,
file_url: url_parse(fileUrl).pathname,
resolved_realm_url: 'realm://' + url_parse(realmUrl).host + body.access_token.token_data.path
});
}
});
}
for (var name in methods) {
methods[name] = {value: methods[name], configurable: true, writable: true}
}
return methods;
}

View File

@ -1,7 +1,7 @@
{ {
"name": "realm", "name": "realm",
"description": "Realm is a mobile database: an alternative to SQLite and key-value stores", "description": "Realm is a mobile database: an alternative to SQLite and key-value stores",
"version": "0.14.3", "version": "0.15.0-rc",
"license": "Apache-2.0", "license": "Apache-2.0",
"homepage": "https://realm.io", "homepage": "https://realm.io",
"keywords": [ "keywords": [
@ -14,7 +14,8 @@
"sqlite", "sqlite",
"asyncstorage", "asyncstorage",
"rocksdb", "rocksdb",
"leveldb" "leveldb",
"realm"
], ],
"author": { "author": {
"name": "Realm", "name": "Realm",
@ -35,29 +36,34 @@
"react-native", "react-native",
"scripts", "scripts",
"src", "src",
"vendor" "vendor",
"binding.gyp",
"dependencies.list"
], ],
"scripts": { "scripts": {
"get-version": "echo $npm_package_version", "get-version": "echo $npm_package_version",
"set-version": "scripts/set-version.sh", "set-version": "scripts/set-version.sh",
"get-core-version": "scripts/download-core.sh --version", "get-core-version": "scripts/download-core.sh --version",
"get-sync-version": "scripts/download-core.sh --versionSync",
"jsdoc": "rm -rf docs/output && jsdoc -c docs/conf.json", "jsdoc": "rm -rf docs/output && jsdoc -c docs/conf.json",
"lint": "eslint", "lint": "eslint",
"test": "scripts/test.sh", "test": "scripts/test.sh",
"install": "node-pre-gyp install --fallback-to-build",
"prepublish": "scripts/prepublish.sh" "prepublish": "scripts/prepublish.sh"
}, },
"dependencies": { "dependencies": {
"bindings": "^1.2.1",
"nan": "^2.3.3", "nan": "^2.3.3",
"node-gyp": "^3.3.1", "needle": "^1.3.0",
"sync-request": "^3.0.1" "node-pre-gyp": "^0.6.30",
"sync-request": "^3.0.1",
"url-parse": "^1.1.7"
}, },
"devDependencies": { "devDependencies": {
"babel-eslint": "^6.0.4", "babel-eslint": "^6.0.4",
"eslint": "^2.10.2", "eslint": "^3.2.2",
"eslint-plugin-react": "^5.1.1", "eslint-plugin-jasmine": "^2.1.0",
"eslint-plugin-react": "^6.7.0",
"jsdoc": "^3.4.0", "jsdoc": "^3.4.0",
"mockery": "^1.7.0",
"semver": "^5.1.0" "semver": "^5.1.0"
}, },
"rnpm": { "rnpm": {
@ -71,5 +77,11 @@
}, },
"engines": { "engines": {
"node": ">=4" "node": ">=4"
},
"binary": {
"module_name": "realm",
"module_path": "./compiled/{node_abi}_{platform}_{arch}/",
"host": "https://static.realm.io",
"remote_path": "/node-pre-gyp"
} }
} }

View File

@ -33,12 +33,14 @@ import org.apache.tools.ant.filters.ReplaceTokens
// After that we build native code from src/main/jni with module path pointing at third-party-ndk. // After that we build native code from src/main/jni with module path pointing at third-party-ndk.
ext.coreVersion = "npm --silent run get-core-version".execute().text.trim() ext.coreVersion = "npm --silent run get-core-version".execute().text.trim()
ext.syncVersion = "npm --silent run get-sync-version".execute().text.trim()
def currentVersion = "npm --silent run get-version".execute().text.trim() def currentVersion = "npm --silent run get-version".execute().text.trim()
def downloadsDir = new File("$projectDir/downloads") def downloadsDir = new File("$projectDir/downloads")
def jscDownloadDir = new File("$projectDir/src/main/jni/jsc") def jscDownloadDir = new File("$projectDir/src/main/jni/jsc")
def coreDownloadDir = new File("$projectDir/src/main/jni") def coreDownloadDir = new File("$projectDir/src/main/jni")
def publishDir = new File("$projectDir/../../android/") def publishDir = new File("$projectDir/../../android/")
// to build with sync run: ./gradlew assembleDebug -PbuildWithSync=true
ext.buildSync = project.hasProperty('buildWithSync') ? project.getProperty('buildWithSync').toBoolean() : false
task generateVersionClass(type: Copy) { task generateVersionClass(type: Copy) {
from 'src/main/templates/Version.java' from 'src/main/templates/Version.java'
@ -64,10 +66,18 @@ task downloadJSCHeaders(type: Download) {
} }
task downloadRealmCore(type: Download) { task downloadRealmCore(type: Download) {
if (project.buildSync) {
src "https://static.realm.io/downloads/sync/realm-sync-android-${project.syncVersion}.tar.gz"
} else {
src "https://static.realm.io/downloads/core/realm-core-android-${project.coreVersion}.tar.gz" src "https://static.realm.io/downloads/core/realm-core-android-${project.coreVersion}.tar.gz"
}
onlyIfNewer true onlyIfNewer true
overwrite false overwrite true
if (project.buildSync) {
dest new File(downloadsDir, "realm-core-android-${project.syncVersion}.tar.gz")
} else {
dest new File(downloadsDir, "realm-core-android-${project.coreVersion}.tar.gz") dest new File(downloadsDir, "realm-core-android-${project.coreVersion}.tar.gz")
}
} }
task prepareRealmCore(dependsOn: downloadRealmCore, type:Copy) { task prepareRealmCore(dependsOn: downloadRealmCore, type:Copy) {
@ -139,6 +149,8 @@ task buildReactNdkLib(dependsOn: [downloadJSCHeaders,prepareRealmCore], type: Ex
inputs.file('src/main/jni') inputs.file('src/main/jni')
outputs.dir("$buildDir/realm-react-ndk/all") outputs.dir("$buildDir/realm-react-ndk/all")
commandLine getNdkBuildFullPath(), commandLine getNdkBuildFullPath(),
'-e',
project.buildSync ? 'BUILD_TYPE_SYNC=1' : 'BUILD_TYPE_SYNC=0',
'NDK_PROJECT_PATH=null', 'NDK_PROJECT_PATH=null',
"NDK_APPLICATION_MK=$projectDir/src/main/jni/Application.mk", "NDK_APPLICATION_MK=$projectDir/src/main/jni/Application.mk",
'NDK_OUT=' + temporaryDir, 'NDK_OUT=' + temporaryDir,

View File

@ -1,5 +1,13 @@
LOCAL_PATH:= $(call my-dir) LOCAL_PATH:= $(call my-dir)
ifeq ($(strip $(BUILD_TYPE_SYNC)),1)
include $(CLEAR_VARS)
LOCAL_MODULE := realm-android-sync-$(TARGET_ARCH_ABI)
LOCAL_EXPORT_C_INCLUDES := core/include
LOCAL_SRC_FILES := core/librealm-sync-android-$(TARGET_ARCH_ABI).a
include $(PREBUILT_STATIC_LIBRARY)
endif
include $(CLEAR_VARS) include $(CLEAR_VARS)
LOCAL_MODULE := realm-android-$(TARGET_ARCH_ABI) LOCAL_MODULE := realm-android-$(TARGET_ARCH_ABI)
LOCAL_EXPORT_C_INCLUDES := core/include LOCAL_EXPORT_C_INCLUDES := core/include
@ -14,34 +22,43 @@ include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS) include $(CLEAR_VARS)
LOCAL_MODULE := librealmreact LOCAL_MODULE := librealmreact
LOCAL_SRC_FILES := \ LOCAL_SRC_FILES := vendor/base64.cpp
src/js_realm.cpp \ LOCAL_SRC_FILES += src/js_realm.cpp
src/rpc.cpp \ LOCAL_SRC_FILES += src/rpc.cpp
src/jsc/jsc_init.cpp \ LOCAL_SRC_FILES += src/jsc/jsc_init.cpp
src/android/platform.cpp \ LOCAL_SRC_FILES += src/android/io_realm_react_RealmReactModule.cpp
src/android/io_realm_react_RealmReactModule.cpp \ LOCAL_SRC_FILES += src/android/jsc_override.cpp
src/android/jsc_override.cpp \ LOCAL_SRC_FILES += src/android/platform.cpp
src/object-store/src/collection_notifications.cpp \ LOCAL_SRC_FILES += src/object-store/src/impl/collection_change_builder.cpp
src/object-store/src/index_set.cpp \ LOCAL_SRC_FILES += src/object-store/src/impl/collection_notifier.cpp
src/object-store/src/list.cpp \ LOCAL_SRC_FILES += src/object-store/src/impl/handover.cpp
src/object-store/src/object_schema.cpp \ LOCAL_SRC_FILES += src/object-store/src/impl/list_notifier.cpp
src/object-store/src/object_store.cpp \ LOCAL_SRC_FILES += src/object-store/src/impl/realm_coordinator.cpp
src/object-store/src/results.cpp \ LOCAL_SRC_FILES += src/object-store/src/impl/results_notifier.cpp
src/object-store/src/schema.cpp \ LOCAL_SRC_FILES += src/object-store/src/impl/transact_log_handler.cpp
src/object-store/src/shared_realm.cpp \ LOCAL_SRC_FILES += src/object-store/src/impl/weak_realm_notifier.cpp
src/object-store/src/parser/parser.cpp \ LOCAL_SRC_FILES += src/object-store/src/impl/android/external_commit_helper.cpp
src/object-store/src/parser/query_builder.cpp \ LOCAL_SRC_FILES += src/object-store/src/parser/parser.cpp
src/object-store/src/impl/collection_change_builder.cpp \ LOCAL_SRC_FILES += src/object-store/src/parser/query_builder.cpp
src/object-store/src/impl/collection_notifier.cpp \ LOCAL_SRC_FILES += src/object-store/src/util/format.cpp
src/object-store/src/impl/list_notifier.cpp \ LOCAL_SRC_FILES += src/object-store/src/util/thread_id.cpp
src/object-store/src/impl/realm_coordinator.cpp \ LOCAL_SRC_FILES += src/object-store/src/collection_notifications.cpp
src/object-store/src/impl/results_notifier.cpp \ LOCAL_SRC_FILES += src/object-store/src/index_set.cpp
src/object-store/src/impl/transact_log_handler.cpp \ LOCAL_SRC_FILES += src/object-store/src/list.cpp
src/object-store/src/impl/android/external_commit_helper.cpp \ LOCAL_SRC_FILES += src/object-store/src/object_schema.cpp
src/object-store/src/impl/android/weak_realm_notifier.cpp \ LOCAL_SRC_FILES += src/object-store/src/object_store.cpp
src/object-store/src/util/format.cpp \ LOCAL_SRC_FILES += src/object-store/src/placeholder.cpp
src/object-store/src/util/thread_id.cpp \ LOCAL_SRC_FILES += src/object-store/src/results.cpp
vendor/base64.cpp LOCAL_SRC_FILES += src/object-store/src/schema.cpp
LOCAL_SRC_FILES += src/object-store/src/shared_realm.cpp
LOCAL_SRC_FILES += src/object-store/src/thread_confined.cpp
ifeq ($(strip $(BUILD_TYPE_SYNC)),1)
LOCAL_SRC_FILES += src/object-store/src/sync/sync_manager.cpp
LOCAL_SRC_FILES += src/object-store/src/sync/sync_session.cpp
LOCAL_SRC_FILES += src/object-store/src/sync/sync_user.cpp
LOCAL_SRC_FILES += src/object-store/src/sync/impl/sync_file.cpp
LOCAL_SRC_FILES += src/object-store/src/sync/impl/sync_metadata.cpp
endif
LOCAL_C_INCLUDES := src LOCAL_C_INCLUDES := src
LOCAL_C_INCLUDES += src/jsc LOCAL_C_INCLUDES += src/jsc
@ -53,9 +70,18 @@ LOCAL_C_INCLUDES += vendor
LOCAL_C_INCLUDES += $(JAVA_HOME)/include LOCAL_C_INCLUDES += $(JAVA_HOME)/include
LOCAL_C_INCLUDES += $(JAVA_HOME)/include/darwin LOCAL_C_INCLUDES += $(JAVA_HOME)/include/darwin
LOCAL_C_INCLUDES += core/include LOCAL_C_INCLUDES += core/include
ifeq ($(strip $(BUILD_TYPE_SYNC)),1)
LOCAL_C_INCLUDES += src/object-store/src/sync
endif
LOCAL_ALLOW_UNDEFINED_SYMBOLS := true LOCAL_ALLOW_UNDEFINED_SYMBOLS := true
ifeq ($(strip $(BUILD_TYPE_SYNC)),1)
LOCAL_STATIC_LIBRARIES := realm-android-sync-$(TARGET_ARCH_ABI)
LOCAL_STATIC_LIBRARIES += realm-android-$(TARGET_ARCH_ABI)
else
LOCAL_STATIC_LIBRARIES := realm-android-$(TARGET_ARCH_ABI) LOCAL_STATIC_LIBRARIES := realm-android-$(TARGET_ARCH_ABI)
endif
LOCAL_SHARED_LIBRARIES := libjsc LOCAL_SHARED_LIBRARIES := libjsc
include $(BUILD_SHARED_LIBRARY) include $(BUILD_SHARED_LIBRARY)

View File

@ -5,7 +5,7 @@ APP_PLATFORM := android-9
APP_MK_DIR := $(dir $(lastword $(MAKEFILE_LIST))) APP_MK_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
NDK_MODULE_PATH := $(APP_MK_DIR)$(HOST_DIRSEP)$(THIRD_PARTY_NDK_DIR)$(HOST_DIRSEP)$(APP_MK_DIR)first-party NDK_MODULE_PATH := $(APP_MK_DIR)$(HOST_DIRSEP)$(THIRD_PARTY_NDK_DIR)$(HOST_DIRSEP)$(APP_MK_DIR)
APP_STL := gnustl_static APP_STL := gnustl_static
APP_CPPFLAGS := -std=c++14 APP_CPPFLAGS := -std=c++14
@ -18,5 +18,8 @@ APP_CPPFLAGS += -fomit-frame-pointer
APP_LDFLAGS := -Wl,--build-id APP_LDFLAGS := -Wl,--build-id
APP_LDFLAGS += -llog APP_LDFLAGS += -llog
APP_LDFLAGS += -landroid APP_LDFLAGS += -landroid
ifeq ($(strip $(BUILD_TYPE_SYNC)),1)
APP_LDFLAGS += -lz
endif
NDK_TOOLCHAIN_VERSION := 4.9 NDK_TOOLCHAIN_VERSION := 4.9

View File

@ -247,6 +247,7 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
CC = "$(SRCROOT)/../../scripts/ccache-clang.sh";
CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "c++14"; CLANG_CXX_LANGUAGE_STANDARD = "c++14";
CLANG_CXX_LIBRARY = "libc++"; CLANG_CXX_LIBRARY = "libc++";
@ -263,6 +264,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CXX = "$(SRCROOT)/../../scripts/ccache-clang++.sh";
DEBUG_INFORMATION_FORMAT = dwarf; DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES; ENABLE_TESTABILITY = YES;
@ -296,6 +298,7 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
CC = "$(SRCROOT)/../../scripts/ccache-clang.sh";
CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "c++14"; CLANG_CXX_LANGUAGE_STANDARD = "c++14";
CLANG_CXX_LIBRARY = "libc++"; CLANG_CXX_LIBRARY = "libc++";
@ -312,6 +315,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CXX = "$(SRCROOT)/../../scripts/ccache-clang++.sh";
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;
@ -341,11 +345,12 @@
HEADER_SEARCH_PATHS = ( HEADER_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"$(SRCROOT)/../../src/**", "$(SRCROOT)/../../src/**",
"$(SRCROOT)/../../vendor", "$(SRCROOT)/../../vendor/core/include",
"$(SRCROOT)/../../vendor/GCDWebServer/GCDWebServer/**", "$(SRCROOT)/../../vendor/GCDWebServer/GCDWebServer/**",
"$(SRCROOT)/../../../react-native/React/**", "$(SRCROOT)/../../../react-native/React/**",
"$(SRCROOT)/../../tests/react-test-app/node_modules/react-native/React/**", "$(SRCROOT)/../../tests/react-test-app/node_modules/react-native/React/**",
"$(SRCROOT)/../../examples/ReactExample/node_modules/react-native/React/**", "$(SRCROOT)/../../examples/ReactExample/node_modules/react-native/React/**",
"$(SRCROOT)/../../vendor",
); );
OTHER_LIBTOOLFLAGS = "$(BUILT_PRODUCTS_DIR)/libRealmJS.a $(BUILT_PRODUCTS_DIR)/libGCDWebServers.a"; OTHER_LIBTOOLFLAGS = "$(BUILT_PRODUCTS_DIR)/libRealmJS.a $(BUILT_PRODUCTS_DIR)/libGCDWebServers.a";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
@ -359,11 +364,12 @@
HEADER_SEARCH_PATHS = ( HEADER_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"$(SRCROOT)/../../src/**", "$(SRCROOT)/../../src/**",
"$(SRCROOT)/../../vendor", "$(SRCROOT)/../../vendor/core/include",
"$(SRCROOT)/../../vendor/GCDWebServer/GCDWebServer/**", "$(SRCROOT)/../../vendor/GCDWebServer/GCDWebServer/**",
"$(SRCROOT)/../../../react-native/React/**", "$(SRCROOT)/../../../react-native/React/**",
"$(SRCROOT)/../../tests/react-test-app/node_modules/react-native/React/**", "$(SRCROOT)/../../tests/react-test-app/node_modules/react-native/React/**",
"$(SRCROOT)/../../examples/ReactExample/node_modules/react-native/React/**", "$(SRCROOT)/../../examples/ReactExample/node_modules/react-native/React/**",
"$(SRCROOT)/../../vendor",
); );
OTHER_LIBTOOLFLAGS = "$(BUILT_PRODUCTS_DIR)/libRealmJS.a"; OTHER_LIBTOOLFLAGS = "$(BUILT_PRODUCTS_DIR)/libRealmJS.a";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0720" LastUpgradeVersion = "0800"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

44
scripts/build-node-pre-gyp.sh Executable file
View File

@ -0,0 +1,44 @@
#!/bin/bash
node_versions=${@:-4.4.7 5.12.0 6.5.0}
topdir=$(cd $(dirname "$0")/..; pwd)
die() {
echo $1
exit 1
}
mkdir -p ${topdir}/out
: ${NVM_DIR=$topdir/.nvm}
if [ ! -d "$NVM_DIR" ]; then
(
git clone https://github.com/creationix/nvm.git "$NVM_DIR"
cd "$NVM_DIR"
git checkout `git describe --abbrev=0 --tags --match "v[0-9]*" origin`
)
fi
if [ -f "$NVM_DIR/nvm.sh" ]; then
. "$NVM_DIR/nvm.sh"
else
# 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"
fi
for node_version in ${node_versions}; do
(
rm -rf node_modules build
nvm install ${node_version} || die "Could not install nodejs v${node_version}"
nvm use ${node_version} || die "Could not load nodejs v${node_version}"
npm install --build-from-source "$EXTRA_NPM_ARGUMENTS" || die "Could not build module"
#./scripts/test.sh node || die "Unit tests for nodejs v${node_version} failed"
./node_modules/.bin/node-pre-gyp package || die "Could not package module"
cp build/stage/node-pre-gyp/*.tar.gz ${topdir}/out/
)
done

11
scripts/ccache-clang++.sh Executable file
View File

@ -0,0 +1,11 @@
#!/bin/sh
if type -p /usr/local/bin/ccache >/dev/null 2>&1; then
export CCACHE_MAXSIZE=10G
export CCACHE_CPP2=true
export CCACHE_HARDLINK=true
export CCACHE_SLOPPINESS=file_macro,time_macros,include_file_mtime,include_file_ctime,file_stat_matches
exec /usr/local/bin/ccache /usr/bin/clang++ "$@"
else
exec clang++ "$@"
fi

11
scripts/ccache-clang.sh Executable file
View File

@ -0,0 +1,11 @@
#!/bin/sh
if type -p /usr/local/bin/ccache >/dev/null 2>&1; then
export CCACHE_MAXSIZE=10G
export CCACHE_CPP2=true
export CCACHE_HARDLINK=true
export CCACHE_SLOPPINESS=file_macro,time_macros,include_file_mtime,include_file_ctime,file_stat_matches
exec /usr/local/bin/ccache /usr/bin/clang "$@"
else
exec clang "$@"
fi

18
scripts/docker-test.sh Executable file
View File

@ -0,0 +1,18 @@
#!/bin/sh
# This is a wrapper script around ./scripts/test.sh which uses docker. The
# arguments are the same, as they are passed directly to test.sh.
# It can be used to locally check and debug the linux build process
# outside of CI.
set -e
./scripts/docker_build_wrapper.sh ci/realm-js:build .
exec docker run --rm \
-u $(id -u) \
-e HOME=/tmp \
-v $(pwd):/source \
-w /source \
ci/realm-js:build \
./scripts/test.sh $@

103
scripts/docker_build_wrapper.sh Executable file
View File

@ -0,0 +1,103 @@
#!/bin/bash
# This is a wrapper script around `docker build`. It provides a mechanism
# for using cached image layers from upstream repositories as well as an
# automatic push back to the docker registry.
set -e
script_path="$(pushd "$(dirname "$0")" >/dev/null; pwd)"
src_path="$(pushd "${script_path}/.." >/dev/null; pwd)"
die() { echo "$@" 1>&2 ; exit 1; }
info() { echo "===> $*"; }
docker_build() {
declare name="$1"; shift
declare path="$1"; shift
declare args="$*"
if [ "${DOCKER_REGISTRY}" != "" ]; then
remote_name="${DOCKER_REGISTRY}/${name}"
fi
info "Building ${name} image..."
if [ "${DOCKER_REGISTRY}" != "" ]; then
docker_pull "${remote_name}" && docker tag "${remote_name}" "${name}" || true
fi
old_id=$(docker images -q "${name}")
info "Old ${name} image id: ${old_id}"
if [ "${DOCKERFILE}" != "" ]; then
docker build ${args} -t "${name}" -f "${DOCKERFILE}" "${path}" || \
die "Building ${name} image failed"
else
docker build ${args} -t "${name}" "${path}" || \
die "Building ${name} image failed"
fi
new_id=$(docker images -q "${name}")
info "New ${name} image id: ${new_id}"
if [ "${DEBUG}" ] && [ "${new_id}" != "${old_id}" ]; then
info "History for old id $old_id:"
if [ "${old_id}" != "" ]; then
docker history "$old_id"
fi
info "History for new id $new_id:"
docker history "$new_id"
fi
if [ "${DOCKER_PUSH:-0}" != "0" ] && [ "${DOCKER_REGISTRY}" != "" ]; then
docker tag "${name}" "${remote_name}"
docker_push "${remote_name}"
fi
}
# Due to https://github.com/docker/docker/issues/20316, we use
# https://github.com/tonistiigi/buildcache to generate a cache of the layer
# metadata for later builds.
my_buildcache() {
if [ "$DOCKER_REGISTRY" != "" ]; then
docker_path="/var/lib/docker"
# Stupid hack for our AWS nodes, which have docker data on another volume
if [ -d "/mnt/docker" ]; then
docker_path="/mnt/docker"
fi
docker pull "${DOCKER_REGISTRY}/ci/buildcache" >/dev/null && \
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v ${docker_path}:/var/lib/docker \
"${DOCKER_REGISTRY}/ci/buildcache" "$@"
fi
}
docker_pull() {
info "Attempting to pull '$1' image from registry..."
(
tmpdir=$(mktemp -d)
docker pull "$1"
(
# In addition, pull the cached metadata and load it (buildcache)
cd "${tmpdir}" && docker pull "$1-cache" && docker save "$1-cache" | \
tar -xf - && docker load -i ./*/layer.tar
)
rm -rf "${tmpdir}"
) || true
}
docker_push() {
info "Pushing '$1' image to registry..."
docker push "$1"
# Create a cache of the layer metdata we need and push it as an image
#docker rmi $1-cache 2>/dev/null || true
my_buildcache save -g /var/lib/docker "$1" | gunzip -c | \
docker import - "$1-cache" && \
docker push "$1-cache"
}
docker_build $@

View File

@ -3,26 +3,50 @@
set -e set -e
set -o pipefail set -o pipefail
source_root="$(dirname "$0")"
# Set to "latest" for the latest build. # Set to "latest" for the latest build.
: ${REALM_CORE_VERSION:=1.5.0} : ${REALM_CORE_VERSION:=$(sed -n 's/^REALM_CORE_VERSION=\(.*\)$/\1/p' ${source_root}/../dependencies.list)}
: ${REALM_SYNC_VERSION:=$(sed -n 's/^REALM_SYNC_VERSION=\(.*\)$/\1/p' ${source_root}/../dependencies.list)}
if [ "$1" = '--version' ]; then if [ "$1" = '--version' ]; then
echo "$REALM_CORE_VERSION" echo "$REALM_CORE_VERSION"
exit 0 exit 0
elif [ "$1" = '--versionSync' ]; then
echo "$REALM_SYNC_VERSION"
exit 0
fi fi
# The 'node' argument will result in realm-node build being downloaded. # The 'node' argument will result in realm-node build being downloaded.
if [ "$1" = 'node' ]; then if [ "$1" = 'node' ]; then
ENABLE_SYNC="$2"
CORE_DIR="core-node" CORE_DIR="core-node"
SYNC_DIR='node-sync'
if [ "$(uname)" = 'Darwin' ]; then if [ "$(uname)" = 'Darwin' ]; then
PLATFORM_TAG="node-osx-"
SYNC_PLATFORM_TAG="node-cocoa-"
CORE_DOWNLOAD_FILE="realm-core-node-osx-$REALM_CORE_VERSION.tar.gz" CORE_DOWNLOAD_FILE="realm-core-node-osx-$REALM_CORE_VERSION.tar.gz"
SYNC_DOWNLOAD_FILE="realm-sync-$SYNC_PLATFORM_TAG$REALM_SYNC_VERSION.zip"
else else
PLATFORM_TAG="node-linux-"
SYNC_PLATFORM_TAG="node-cocoa-"
CORE_DOWNLOAD_FILE="realm-core-node-linux-$REALM_CORE_VERSION.tar.gz" CORE_DOWNLOAD_FILE="realm-core-node-linux-$REALM_CORE_VERSION.tar.gz"
SYNC_DOWNLOAD_FILE=""
fi fi
SYNC_EXTRACT="unzip"
EXTRACTED_DIR="realm-sync-node-cocoa-$REALM_SYNC_VERSION"
else else
ENABLE_SYNC="yes" # FIXME: This means that both core and sync will be downloaded for non "node" targets.
# Should be 0 or 1. We do not need to download both
CORE_DIR='core' CORE_DIR='core'
CORE_DOWNLOAD_FILE="realm-core-$REALM_CORE_VERSION.tar.xz" PLATFORM_TAG=""
SYNC_DIR='sync'
CORE_DOWNLOAD_FILE="realm-core-$PLATFORM_TAG$REALM_CORE_VERSION.tar.xz"
SYNC_DOWNLOAD_FILE="realm-sync-cocoa-$SYNC_PLATFORM_TAG$REALM_SYNC_VERSION.tar.xz"
SYNC_EXTRACT="tar -xvf"
EXTRACTED_DIR="core"
fi fi
# Start current working directory at the root of the project. # Start current working directory at the root of the project.
@ -34,57 +58,119 @@ die() {
} }
download_core() { download_core() {
echo "Downloading dependency: $CORE_DIR $REALM_CORE_VERSION" local DIR=$1
local VERSION=$2
local DOWNLOAD_FILE=$3
local SERVER_DIR=$4
local UNTAR=$5
local UNTARRED_DIR=$6
echo "Downloading dependency: $DIR $VERSION"
local TMP_DIR="${TMPDIR:-/tmp}/core_bin" local TMP_DIR="${TMPDIR:-/tmp}/$DIR"
local CORE_TAR="$TMP_DIR/$CORE_DOWNLOAD_FILE" local TAR="$TMP_DIR/$DOWNLOAD_FILE"
local CORE_TMP_TAR="$CORE_TAR.tmp" local TMP_TAR="$TAR.tmp"
mkdir -p "$TMP_DIR" mkdir -p "$TMP_DIR"
if [ ! -f "$CORE_TAR" ]; then if [ ! -f "$TAR" ]; then
curl -f -L -s "https://static.realm.io/downloads/core/$CORE_DOWNLOAD_FILE" -o "$CORE_TMP_TAR" || echo "https://static.realm.io/downloads/$SERVER_DIR/$DOWNLOAD_FILE"
die "Downloading $CORE_DIR failed. Please try again once you have an Internet connection." curl -f -L -s "https://static.realm.io/downloads/$SERVER_DIR/$DOWNLOAD_FILE" -o "$TMP_TAR" ||
mv "$CORE_TMP_TAR" "$CORE_TAR" die "Downloading $DIR failed. Please try again once you have an Internet connection."
mv "$TMP_TAR" "$TAR"
else else
echo "Using cached $CORE_DIR from TMPDIR" echo "Using cached $DIR from TMPDIR"
fi fi
( (
cd "$TMP_DIR" cd "$TMP_DIR"
rm -rf "$CORE_DIR" rm -rf "$DIR"
tar -xzf "$CORE_TAR" eval "$UNTAR" "$TAR"
mv core "$CORE_DIR-$REALM_CORE_VERSION" mv "$UNTARRED_DIR" "$DIR-$VERSION"
) )
rm -rf "$CORE_DIR-$REALM_CORE_VERSION" "$CORE_DIR" (
mv "$TMP_DIR/$CORE_DIR-$REALM_CORE_VERSION" . cd vendor
ln -s "$CORE_DIR-$REALM_CORE_VERSION" "$CORE_DIR" rm -rf "$DIR-$VERSION" "$DIR"
mv "$TMP_DIR/$DIR-$VERSION" .
ln -s "$DIR-$VERSION" "$DIR"
)
} }
check_release_notes() { check_release_notes() {
grep -Fqi "$REALM_CORE_VERSION RELEASE NOTES" "$@" grep -Fqi "$REALM_CORE_VERSION RELEASE NOTES" "$@"
} }
if [ ! -e "$CORE_DIR" ]; then DOWNLOAD_CORE=1
download_core
elif [ -d "$CORE_DIR" -a -d ../realm-core -a ! -L "$CORE_DIR" ]; then if ! [ -z "$REALM_CORE_PREFIX" ]; then
DOWNLOAD_CORE=0
echo "Skipping the core download because REALM_CORE_PREFIX is defined."
fi
if [ "$ENABLE_SYNC" == 1 ]; then
DOWNLOAD_CORE=0
echo "Skipping the core download because ENABLE_SYNC is true."
fi
if [ "$DOWNLOAD_CORE" == 1 ]; then
if [ ! -e "vendor/$CORE_DIR" ]; then
download_core $CORE_DIR $REALM_CORE_VERSION $CORE_DOWNLOAD_FILE core "tar -xzf" core
elif [ -d "vendor/$CORE_DIR" -a -d ../realm-core -a ! -L "vendor/$CORE_DIR" ]; then
# Allow newer versions than expected for local builds as testing # Allow newer versions than expected for local builds as testing
# with unreleased versions is one of the reasons to use a local build # with unreleased versions is one of the reasons to use a local build
if ! check_release_notes "$CORE_DIR/release_notes.txt"; then if ! check_release_notes "vendor/$CORE_DIR/CHANGELOG.txt"; then
die "Local build of core is out of date." die "Local build of core is out of date."
else else
echo "The core library seems to be up to date." echo "The core library seems to be up to date."
fi fi
elif [ ! -L "$CORE_DIR" ]; then elif [ ! -L "vendor/$CORE_DIR" ]; then
echo "$CORE_DIR is not a symlink. Deleting..." echo "vendor/$CORE_DIR is not a symlink. Deleting..."
rm -rf "$CORE_DIR" rm -rf "vendor/$CORE_DIR"
download_core download_core $CORE_DIR $REALM_CORE_VERSION $CORE_DOWNLOAD_FILE core "tar -xzf" core
# With a prebuilt version we only want to check the first non-empty # With a prebuilt version we only want to check the first non-empty
# line so that checking out an older commit will download the # line so that checking out an older commit will download the
# appropriate version of core if the already-present version is too new # appropriate version of core if the already-present version is too new
elif ! grep -m 1 . "$CORE_DIR/release_notes.txt" | check_release_notes; then elif ! grep -m 1 . "vendor/$CORE_DIR/CHANGELOG.txt" | check_release_notes; then
download_core download_core $CORE_DIR $REALM_CORE_VERSION $CORE_DOWNLOAD_FILE core "tar -xzf" core
else else
echo "The core library seems to be up to date." echo "The core library seems to be up to date."
fi
fi
DOWNLOAD_SYNC=1
if ! [ -z "$REALM_SYNC_PREFIX" ]; then
DOWNLOAD_SYNC=0
echo "Skipping the sync download because REALM_SYNC_PREFIX is defined."
fi
if [ "$ENABLE_SYNC" == 0 ]; then
DOWNLOAD_SYNC=0
echo "Skipping the sync download because ENABLE_SYNC is false."
fi
if [ "$DOWNLOAD_SYNC" == 1 ]; then
if [ -n "$SYNC_DOWNLOAD_FILE" ];then
if [ ! -e "vendor/$SYNC_DIR" ]; then
download_core $SYNC_DIR $REALM_SYNC_VERSION $SYNC_DOWNLOAD_FILE sync "$SYNC_EXTRACT" $EXTRACTED_DIR
elif [ -d "vendor/$SYNC_DIR" -a -d ../realm-sync -a ! -L "vendor/$SYNC_DIR" ]; then
# Allow newer versions than expected for local builds as testing
# with unreleased versions is one of the reasons to use a local build
if ! check_release_notes "vendor/$SYNC_DIR/version.txt"; then
die "Local build of sync is out of date."
else
echo "The sync library seems to be up to date."
fi
elif [ ! -L "vendor/$SYNC_DIR" ]; then
echo "vendor/$SYNC_DIR is not a symlink. Deleting..."
rm -rf "vendor/$SYNC_DIR"
download_core $SYNC_DIR $REALM_SYNC_VERSION $SYNC_DOWNLOAD_FILE sync "$SYNC_EXTRACT" $EXTRACTED_DIR
# With a prebuilt version we only want to check the first non-empty
# line so that checking out an older commit will download the
# appropriate version of core if the already-present version is too new
elif ! grep -m 1 . "vendor/$SYNC_DIR/version.txt"; then
download_core $SYNC_DIR $REALM_SYNC_VERSION $SYNC_DOWNLOAD_FILE sync "$SYNC_EXTRACT" $EXTRACTED_DIR
else
echo "The sync library seems to be up to date."
fi
fi
fi fi

View File

@ -0,0 +1,25 @@
#!/bin/bash
set -eo pipefail
[ "$(uname -s)" != "Darwin" ] && exit
. dependencies.list
if [ -f object-server-for-testing/node_modules/realm-object-server/CHANGELOG.md ]; then
current_version=$(head -n1 object-server-for-testing/node_modules/realm-object-server/CHANGELOG.md | cut -d" " -f2)
if [ "$REALM_OBJECT_SERVER_VERSION" = "$current_version" ]; then
echo -e "yes\n" | object-server-for-testing/reset-server-realms.command
exit
fi
fi
object_server_bundle="realm-object-server-bundled_node_darwin-$REALM_OBJECT_SERVER_VERSION.tar.gz"
curl -f -L "https://static.realm.io/downloads/object-server/$object_server_bundle" -o "$object_server_bundle"
rm -rf object-server-for-testing
mkdir object-server-for-testing
tar -C object-server-for-testing -xf "$object_server_bundle"
rm "$object_server_bundle"
echo -e "enterprise:\n skip_setup: true\n" >> "object-server-for-testing/object-server/configuration.yml"
touch "object-server-for-testing/object-server/do_not_open_browser"

View File

@ -8,5 +8,5 @@ cd "$(dirname "$0")/.."
if [ -n "$REALM_BUILD_ANDROID" ]; then if [ -n "$REALM_BUILD_ANDROID" ]; then
rm -rf android rm -rf android
(cd react-native/android && ./gradlew publishAndroid) (cd react-native/android && ./gradlew publishAndroid -PbuildWithSync=true)
fi fi

View File

@ -3,57 +3,50 @@
set -o pipefail set -o pipefail
set -e set -e
export REALM_SWIFT_VERSION=3.0.1
if [[ -z "$DEVELOPER_DIR" ]]; then
export DEVELOPER_DIR="$(xcode-select -p)"
fi
while pgrep -q Simulator; do while pgrep -q Simulator; do
# Kill all the current simulator processes as they may be from a # Kill all the current simulator processes as they may be from a
# different Xcode version # different Xcode version
pkill Simulator 2>/dev/null || true pkill Simulator 2>/dev/null || true
# CoreSimulatorService doesn't exit when sent SIGTERM # CoreSimulatorService doesn't exit when sent SIGTERM
pkill -9 Simulator 2>/dev/null || true pkill -9 Simulator 2>/dev/null || true
done
# Shut down simulators until there's no booted ones left
# Only do one at a time because devices sometimes show up multiple times
while xcrun simctl list | grep -q Booted; do
xcrun simctl list | grep Booted | sed 's/.* (\(.*\)) (Booted)/\1/' | head -n 1 | xargs xcrun simctl shutdown
done done
# Clean up all available simulators # Run until we get a result since switching simulator versions often causes CoreSimulatorService to throw an exception.
( devices=""
previous_device='' until [ "$devices" != "" ]; do
IFS=$'\n' # make newlines the only separator devices="$(xcrun simctl list devices -j || true)"
for LINE in $(xcrun simctl list); do done
if [[ $LINE =~ unavailable || $LINE =~ disconnected ]]; then
# skip unavailable simulators
continue
fi
if [[ $LINE =~ "--" ]]; then # Shut down booted simulators
# Reset the last seen device so we won't consider devices with the same name to be duplicates echo "$devices" | ruby -rjson -e 'puts JSON.parse($stdin.read)["devices"].flat_map { |d| d[1] }.select { |d| d["state"] == "Booted" && d["availability"] == "(available)" }.map { |d| d["udid"] }' | while read udid; do
# if they appear in different sections. echo "shutting down simulator with ID: $udid"
previous_device="" xcrun simctl shutdown $udid
continue done
fi
regex='^(.*) [(]([0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12})[)]' # Erase all available simulators
if [[ $LINE =~ $regex ]]; then echo "erasing simulators"
device="${BASH_REMATCH[1]}" echo "$devices" | ruby -rjson -e 'puts JSON.parse($stdin.read)["devices"].flat_map { |d| d[1] }.select { |d| d["availability"] == "(available)" }.map { |d| d["udid"] }' | while read udid; do
guid="${BASH_REMATCH[2]}" xcrun simctl erase $udid &
done
wait
# Delete the simulator if it's a duplicate of the last seen one xcrun simctl boot "iPhone 5" # React Native seems to want to test with this device
# Otherwise delete all contents and settings for it
if [[ $device == $previous_device ]]; then
xcrun simctl delete $guid
else
xcrun simctl erase $guid
previous_device="$device"
fi
fi
done
)
if [[ -a "${DEVELOPER_DIR}/Applications/iOS Simulator.app" ]]; then if [[ -a "${DEVELOPER_DIR}/Applications/Simulator.app" ]]; then
open "${DEVELOPER_DIR}/Applications/iOS Simulator.app"
elif [[ -a "${DEVELOPER_DIR}/Applications/Simulator.app" ]]; then
open "${DEVELOPER_DIR}/Applications/Simulator.app" open "${DEVELOPER_DIR}/Applications/Simulator.app"
fi fi
# Wait until the boot completes
echo "waiting for simulator to boot..."
until xcrun simctl list devices -j | ruby -rjson -e 'exit JSON.parse($stdin.read)["devices"].flat_map { |d| d[1] }.any? { |d| d["availability"] == "(available)" && d["state"] == "Booted" }'; do
sleep 1
done
# Wait until the simulator is fully booted by waiting for it to launch SpringBoard
xcrun simctl launch booted com.apple.springboard >/dev/null 2>&1 || true
echo "simulator booted"

View File

@ -11,6 +11,7 @@ CONFIGURATION="${2:-"Release"}"
DESTINATION= DESTINATION=
PATH="/opt/android-sdk-linux/platform-tools:$PATH" PATH="/opt/android-sdk-linux/platform-tools:$PATH"
SRCROOT=$(cd "$(dirname "$0")/.." && pwd) SRCROOT=$(cd "$(dirname "$0")/.." && pwd)
XCPRETTY=true
# Start current working directory at the root of the project. # Start current working directory at the root of the project.
cd "$SRCROOT" cd "$SRCROOT"
@ -23,12 +24,34 @@ if [[ $TARGET = *-android ]]; then
export REALM_BUILD_ANDROID=1 export REALM_BUILD_ANDROID=1
fi fi
SERVER_PID=0
PACKAGER_OUT="$SRCROOT/packager_out.txt" PACKAGER_OUT="$SRCROOT/packager_out.txt"
LOGCAT_OUT="$SRCROOT/logcat_out.txt" LOGCAT_OUT="$SRCROOT/logcat_out.txt"
download_server() {
sh ./scripts/download-object-server.sh
}
start_server() {
sh ./object-server-for-testing/start-object-server.command &
SERVER_PID=$!
}
stop_server() {
if [[ ${SERVER_PID} > 0 ]] ; then
kill ${SERVER_PID}
fi
}
cleanup() { cleanup() {
# Kill all child processes. # Kill started object server
stop_server
# Kill all other child processes.
pkill -P $$ || true pkill -P $$ || true
# Kill react native packager
pkill node || true pkill node || true
rm -f "$PACKAGER_OUT" "$LOGCAT_OUT" rm -f "$PACKAGER_OUT" "$LOGCAT_OUT"
} }
@ -58,13 +81,15 @@ start_packager() {
} }
xctest() { xctest() {
${SRCROOT}/scripts/reset-simulators.sh
local dest="$(xcrun simctl list devices | grep -v unavailable | grep -m 1 -o '[0-9A-F\-]\{36\}')" local dest="$(xcrun simctl list devices | grep -v unavailable | grep -m 1 -o '[0-9A-F\-]\{36\}')"
if [ -n "$XCPRETTY" ]; then if [ -n "$XCPRETTY" ]; then
xcodebuild -scheme "$1" -configuration "$CONFIGURATION" -sdk iphonesimulator -destination id="$dest" test | xcpretty -c --no-utf --report junit --output build/reports/junit.xml mkdir -p build
xcodebuild -scheme "$1" -configuration "$CONFIGURATION" -sdk iphonesimulator -destination id="$dest" build test | tee build/build.log | xcpretty -c --no-utf --report junit --output build/reports/junit.xml || {
echo "The raw xcodebuild output is available in build/build.log"
exit 1
}
else else
xcodebuild -scheme "$1" -configuration "$CONFIGURATION" -sdk iphonesimulator -destination id="$dest" test xcodebuild -scheme "$1" -configuration "$CONFIGURATION" -sdk iphonesimulator -destination id="$dest" build test
fi fi
} }
@ -75,9 +100,12 @@ trap cleanup EXIT
# Use a consistent version of Node if possible. # Use a consistent version of Node if possible.
if [ -s "${HOME}/.nvm/nvm.sh" ]; then if [ -s "${HOME}/.nvm/nvm.sh" ]; then
. "${HOME}/.nvm/nvm.sh" . "${HOME}/.nvm/nvm.sh"
nvm use 5.4.0 || true nvm use 4.4.7 || true
fi fi
# Remove cached packages
rm -rf ~/.yarn-cache/npm-realm-*
case "$TARGET" in case "$TARGET" in
"eslint") "eslint")
[[ $CONFIGURATION == 'Debug' ]] && exit 0 [[ $CONFIGURATION == 'Debug' ]] && exit 0
@ -94,35 +122,36 @@ case "$TARGET" in
xctest RealmJS xctest RealmJS
;; ;;
"react-tests") "react-tests")
if ! [ -z "${JENKINS_HOME}" ]; then
${SRCROOT}/scripts/reset-simulators.sh
fi
pushd tests/react-test-app pushd tests/react-test-app
if [ -f ../../target=node_modules/react_tests_node_modules.zip ]; then
unzip -q ../../target=node_modules/react_tests_node_modules.zip
fi
npm install npm install
open_chrome open_chrome
start_packager start_packager
pushd ios pushd ios
xctest ReactTestApp xctest ReactTestApp || xctest ReactTestApp
;; ;;
"react-example") "react-example")
pushd examples/ReactExample if ! [ -z "${JENKINS_HOME}" ]; then
${SRCROOT}/scripts/reset-simulators.sh
if [ -f ../../target=node_modules/react_example_node_modules.zip ]; then
unzip -q ../../target=node_modules/react_example_node_modules.zip
fi fi
pushd examples/ReactExample
npm install npm install
open_chrome open_chrome
start_packager start_packager
pushd ios pushd ios
xctest ReactExample xctest ReactExample || xctest ReactExample
;; ;;
"react-tests-android") "react-tests-android")
[[ $CONFIGURATION == 'Debug' ]] && exit 0 [[ $CONFIGURATION == 'Debug' ]] && exit 0
XCPRETTY=false
pushd tests/react-test-app pushd tests/react-test-app
@ -154,20 +183,40 @@ case "$TARGET" in
cat tests.xml cat tests.xml
;; ;;
"node") "node")
npm install if [ "$(uname)" = 'Darwin' ]; then
scripts/download-core.sh node download_server
src/node/build-node.sh $CONFIGURATION start_server
npm_tests_cmd="npm run test"
npm install --build-from-source --realm_enable_sync
else
npm_tests_cmd="npm run test-nosync"
npm install --build-from-source
fi
# Change to a temp directory. # Change to a temp directory.
cd "$(mktemp -q -d -t realm.node.XXXXXX)" cd "$(mktemp -q -d -t realm.node.XXXXXX)"
trap "rm -rf '$PWD'" EXIT trap "rm -rf '$PWD'" EXIT
node "$SRCROOT/tests" pushd "$SRCROOT/tests"
npm install
eval $npm_tests_cmd
popd
stop_server
;;
"node-nosync")
npm install --build-from-source
# Change to a temp directory.
cd "$(mktemp -q -d -t realm.node.XXXXXX)"
trap "rm -rf '$PWD'" EXIT
pushd "$SRCROOT/tests"
npm install
npm run test-nosync
popd
;; ;;
"test-runners") "test-runners")
npm install npm install --build-from-source
scripts/download-core.sh node
src/node/build-node.sh $CONFIGURATION
for runner in ava mocha jest; do for runner in ava mocha jest; do
pushd "$SRCROOT/tests/test-runners/$runner" pushd "$SRCROOT/tests/test-runners/$runner"
@ -181,6 +230,27 @@ case "$TARGET" in
cmake -DCMAKE_BUILD_TYPE=$CONFIGURATION . cmake -DCMAKE_BUILD_TYPE=$CONFIGURATION .
make run-tests make run-tests
;; ;;
"download-object-server")
. dependencies.list
object_server_bundle="realm-object-server-bundled_node_darwin-$REALM_OBJECT_SERVER_VERSION.tar.gz"
curl -f -L "https://static.realm.io/downloads/object-server/$object_server_bundle" -o "$object_server_bundle"
rm -rf tests/sync-bundle
mkdir -p tests/sync-bundle
tar -C tests/sync-bundle -xf "$object_server_bundle"
rm "$object_server_bundle"
echo -e "enterprise:\n skip_setup: true\n" >> "tests/sync-bundle/object-server/configuration.yml"
touch "tests/sync-bundle/object-server/do_not_open_browser"
;;
"object-server-integration")
echo -e "yes\n" | ./tests/sync-bundle/reset-server-realms.command
pushd "$SRCROOT/tests"
npm install
npm run test-sync-integration
popd
;;
*) *)
echo "Invalid target '${TARGET}'" echo "Invalid target '${TARGET}'"
exit 1 exit 1

View File

@ -7,6 +7,13 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
02022A581DA476CD000F0C4F /* external_commit_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02022A411DA47489000F0C4F /* external_commit_helper.cpp */; };
02022A5A1DA476CD000F0C4F /* weak_realm_notifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02022A4A1DA475A9000F0C4F /* weak_realm_notifier.cpp */; };
02022A5B1DA476CD000F0C4F /* placeholder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02022A4C1DA475C0000F0C4F /* placeholder.cpp */; };
02022A671DA47BD7000F0C4F /* parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02022A611DA47B8B000F0C4F /* parser.cpp */; };
02022A681DA47BD7000F0C4F /* query_builder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02022A631DA47B8B000F0C4F /* query_builder.cpp */; };
02022A7C1DA47EC8000F0C4F /* format.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02022A731DA47EC8000F0C4F /* format.cpp */; };
02022A7D1DA47EC8000F0C4F /* thread_id.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02022A791DA47EC8000F0C4F /* thread_id.cpp */; };
02409DC21BCF11D6005F3B3E /* RealmJSCoreTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 02409DC11BCF11D6005F3B3E /* RealmJSCoreTests.m */; }; 02409DC21BCF11D6005F3B3E /* RealmJSCoreTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 02409DC11BCF11D6005F3B3E /* RealmJSCoreTests.m */; };
02414B881CE68CA200A8669F /* dates-v5.realm in Resources */ = {isa = PBXBuildFile; fileRef = 02414B871CE68CA200A8669F /* dates-v5.realm */; }; 02414B881CE68CA200A8669F /* dates-v5.realm in Resources */ = {isa = PBXBuildFile; fileRef = 02414B871CE68CA200A8669F /* dates-v5.realm */; };
02414BA51CE6ABCF00A8669F /* collection_change_builder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02414B991CE6AAEF00A8669F /* collection_change_builder.cpp */; }; 02414BA51CE6ABCF00A8669F /* collection_change_builder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02414B991CE6AAEF00A8669F /* collection_change_builder.cpp */; };
@ -18,7 +25,12 @@
027A23131CD3E379000543AE /* libRealmJS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F63FF2B11C1241E500B3B8E0 /* libRealmJS.a */; }; 027A23131CD3E379000543AE /* libRealmJS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F63FF2B11C1241E500B3B8E0 /* libRealmJS.a */; };
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 */; }; 02E315C91DB80DDD00555337 /* sync_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02E315C31DB80DDD00555337 /* sync_manager.cpp */; };
02E315CA1DB80DDD00555337 /* sync_session.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02E315C51DB80DDD00555337 /* sync_session.cpp */; };
02E315CB1DB80DDD00555337 /* sync_user.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02E315C71DB80DDD00555337 /* sync_user.cpp */; };
02E315D21DB80DF200555337 /* sync_file.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02E315CE1DB80DF200555337 /* sync_file.cpp */; };
02E315D31DB80DF200555337 /* sync_metadata.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02E315D01DB80DF200555337 /* sync_metadata.cpp */; };
02E315E01DB8233E00555337 /* keychain_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02E315DE1DB8233E00555337 /* keychain_helper.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 */; };
@ -26,34 +38,12 @@
02F59EC31C88F17D007F774C /* results.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EB91C88F17D007F774C /* results.cpp */; }; 02F59EC31C88F17D007F774C /* results.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EB91C88F17D007F774C /* results.cpp */; };
02F59EC41C88F17D007F774C /* schema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EBB1C88F17D007F774C /* schema.cpp */; }; 02F59EC41C88F17D007F774C /* schema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EBB1C88F17D007F774C /* schema.cpp */; };
02F59EC51C88F17D007F774C /* shared_realm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EBD1C88F17D007F774C /* shared_realm.cpp */; }; 02F59EC51C88F17D007F774C /* shared_realm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EBD1C88F17D007F774C /* shared_realm.cpp */; };
02F59ECA1C88F190007F774C /* parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EC61C88F190007F774C /* parser.cpp */; };
02F59ECB1C88F190007F774C /* query_builder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EC81C88F190007F774C /* query_builder.cpp */; };
02F59ED41C88F1B6007F774C /* external_commit_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59ECF1C88F1B6007F774C /* external_commit_helper.cpp */; };
02F59ED51C88F1B6007F774C /* weak_realm_notifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59ED11C88F1B6007F774C /* weak_realm_notifier.cpp */; };
02F59EE21C88F2BB007F774C /* realm_coordinator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EDB1C88F2BA007F774C /* realm_coordinator.cpp */; }; 02F59EE21C88F2BB007F774C /* realm_coordinator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EDB1C88F2BA007F774C /* realm_coordinator.cpp */; };
02F59EE31C88F2BB007F774C /* transact_log_handler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EDD1C88F2BB007F774C /* transact_log_handler.cpp */; }; 02F59EE31C88F2BB007F774C /* transact_log_handler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EDD1C88F2BB007F774C /* transact_log_handler.cpp */; };
5D25F5A11D6284FD00EBBB30 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = F63FF3301C16434400B3B8E0 /* libz.tbd */; };
5DC74A781D623C9800D77A4F /* handover.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5DC74A751D623C8700D77A4F /* handover.cpp */; }; 5DC74A781D623C9800D77A4F /* handover.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5DC74A751D623C8700D77A4F /* handover.cpp */; };
5DC74A791D623CA200D77A4F /* handover.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5DC74A751D623C8700D77A4F /* handover.cpp */; };
5DC74A7A1D623CA800D77A4F /* thread_confined.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5DC74A721D623C7A00D77A4F /* thread_confined.cpp */; }; 5DC74A7A1D623CA800D77A4F /* thread_confined.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5DC74A721D623C7A00D77A4F /* thread_confined.cpp */; };
5DC74A7B1D623CA800D77A4F /* thread_confined.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5DC74A721D623C7A00D77A4F /* thread_confined.cpp */; };
F60102D31CBB966E00EC01BA /* js_realm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 029048071C0428DF00ABDED4 /* js_realm.cpp */; };
F60102D41CBB96AB00EC01BA /* index_set.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EAF1C88F17D007F774C /* index_set.cpp */; };
F60102D51CBB96AE00EC01BA /* list.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EB11C88F17D007F774C /* list.cpp */; };
F60102D61CBB96B400EC01BA /* object_schema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EB41C88F17D007F774C /* object_schema.cpp */; };
F60102D71CBB96B800EC01BA /* object_store.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EB61C88F17D007F774C /* object_store.cpp */; };
F60102D81CBB96BD00EC01BA /* results.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EB91C88F17D007F774C /* results.cpp */; };
F60102D91CBB96C100EC01BA /* schema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EBB1C88F17D007F774C /* schema.cpp */; };
F60102DA1CBB96C300EC01BA /* shared_realm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EBD1C88F17D007F774C /* shared_realm.cpp */; };
F60102DB1CBB96C600EC01BA /* parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EC61C88F190007F774C /* parser.cpp */; };
F60102DC1CBB96C900EC01BA /* query_builder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EC81C88F190007F774C /* query_builder.cpp */; };
F60102DD1CBB96CC00EC01BA /* external_commit_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59ECF1C88F1B6007F774C /* external_commit_helper.cpp */; };
F60102E01CBB96D900EC01BA /* realm_coordinator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EDB1C88F2BA007F774C /* realm_coordinator.cpp */; };
F60102E11CBB96DD00EC01BA /* transact_log_handler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EDD1C88F2BB007F774C /* transact_log_handler.cpp */; };
F60102EA1CBCAFC300EC01BA /* node_dummy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F6267BCA1CADC49200AC36B1 /* node_dummy.cpp */; };
F61378791C18EAC5008BFC51 /* js in Resources */ = {isa = PBXBuildFile; fileRef = F61378781C18EAAC008BFC51 /* js */; }; F61378791C18EAC5008BFC51 /* js in Resources */ = {isa = PBXBuildFile; fileRef = F61378781C18EAAC008BFC51 /* js */; };
F620F0581CB766DA0082977B /* node_init.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F620F0571CB766DA0082977B /* node_init.cpp */; };
F620F0751CB9F60C0082977B /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F620F0741CB9F60C0082977B /* CoreFoundation.framework */; };
F63117F01CEB0D5F00ECB2DE /* weak_realm_notifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F63117EE1CEB0D5900ECB2DE /* weak_realm_notifier.cpp */; };
F63FF2C61C12469E00B3B8E0 /* jsc_init.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 029048011C0428DF00ABDED4 /* jsc_init.cpp */; }; F63FF2C61C12469E00B3B8E0 /* jsc_init.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 029048011C0428DF00ABDED4 /* jsc_init.cpp */; };
F63FF2C91C12469E00B3B8E0 /* js_realm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 029048071C0428DF00ABDED4 /* js_realm.cpp */; }; F63FF2C91C12469E00B3B8E0 /* js_realm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 029048071C0428DF00ABDED4 /* js_realm.cpp */; };
F63FF2CD1C12469E00B3B8E0 /* rpc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0290480F1C0428DF00ABDED4 /* rpc.cpp */; }; F63FF2CD1C12469E00B3B8E0 /* rpc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0290480F1C0428DF00ABDED4 /* rpc.cpp */; };
@ -72,17 +62,8 @@
F63FF3251C1642BB00B3B8E0 /* GCDWebServerErrorResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = F63FF3161C1642BB00B3B8E0 /* GCDWebServerErrorResponse.m */; }; F63FF3251C1642BB00B3B8E0 /* GCDWebServerErrorResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = F63FF3161C1642BB00B3B8E0 /* GCDWebServerErrorResponse.m */; };
F63FF3261C1642BB00B3B8E0 /* GCDWebServerFileResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = F63FF3181C1642BB00B3B8E0 /* GCDWebServerFileResponse.m */; }; F63FF3261C1642BB00B3B8E0 /* GCDWebServerFileResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = F63FF3181C1642BB00B3B8E0 /* GCDWebServerFileResponse.m */; };
F63FF3271C1642BB00B3B8E0 /* GCDWebServerStreamedResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = F63FF31A1C1642BB00B3B8E0 /* GCDWebServerStreamedResponse.m */; }; F63FF3271C1642BB00B3B8E0 /* GCDWebServerStreamedResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = F63FF31A1C1642BB00B3B8E0 /* GCDWebServerStreamedResponse.m */; };
F64A059B1D10D928004ACDBE /* format.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02E008D21D10AB1B00F3AA37 /* format.cpp */; };
F64A059D1D13710C004ACDBE /* thread_id.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F64A059C1D13710C004ACDBE /* thread_id.cpp */; };
F64A059E1D13710C004ACDBE /* thread_id.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F64A059C1D13710C004ACDBE /* thread_id.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 */
@ -98,6 +79,27 @@
/* End PBXCopyFilesBuildPhase section */ /* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
02022A411DA47489000F0C4F /* external_commit_helper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = external_commit_helper.cpp; sourceTree = "<group>"; };
02022A421DA47489000F0C4F /* external_commit_helper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = external_commit_helper.hpp; sourceTree = "<group>"; };
02022A481DA474A7000F0C4F /* weak_realm_notifier.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = weak_realm_notifier.hpp; sourceTree = "<group>"; };
02022A4A1DA475A9000F0C4F /* weak_realm_notifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = weak_realm_notifier.cpp; sourceTree = "<group>"; };
02022A4C1DA475C0000F0C4F /* placeholder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = placeholder.cpp; path = src/placeholder.cpp; sourceTree = "<group>"; };
02022A611DA47B8B000F0C4F /* parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parser.cpp; sourceTree = "<group>"; };
02022A621DA47B8B000F0C4F /* parser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = parser.hpp; sourceTree = "<group>"; };
02022A631DA47B8B000F0C4F /* query_builder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = query_builder.cpp; sourceTree = "<group>"; };
02022A641DA47B8B000F0C4F /* query_builder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = query_builder.hpp; sourceTree = "<group>"; };
02022A6D1DA47EC8000F0C4F /* event_loop_signal.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = event_loop_signal.hpp; sourceTree = "<group>"; };
02022A6F1DA47EC8000F0C4F /* event_loop_signal.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = event_loop_signal.hpp; sourceTree = "<group>"; };
02022A701DA47EC8000F0C4F /* atomic_shared_ptr.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = atomic_shared_ptr.hpp; sourceTree = "<group>"; };
02022A711DA47EC8000F0C4F /* compiler.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = compiler.hpp; sourceTree = "<group>"; };
02022A721DA47EC8000F0C4F /* event_loop_signal.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = event_loop_signal.hpp; sourceTree = "<group>"; };
02022A731DA47EC8000F0C4F /* format.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = format.cpp; sourceTree = "<group>"; };
02022A741DA47EC8000F0C4F /* format.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = format.hpp; sourceTree = "<group>"; };
02022A761DA47EC8000F0C4F /* event_loop_signal.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = event_loop_signal.hpp; sourceTree = "<group>"; };
02022A781DA47EC8000F0C4F /* event_loop_signal.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = event_loop_signal.hpp; sourceTree = "<group>"; };
02022A791DA47EC8000F0C4F /* thread_id.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thread_id.cpp; sourceTree = "<group>"; };
02022A7A1DA47EC8000F0C4F /* thread_id.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = thread_id.hpp; sourceTree = "<group>"; };
02022A7B1DA47EC8000F0C4F /* thread_local.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = thread_local.hpp; sourceTree = "<group>"; };
02409DC11BCF11D6005F3B3E /* RealmJSCoreTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RealmJSCoreTests.m; path = ios/RealmJSCoreTests.m; sourceTree = "<group>"; }; 02409DC11BCF11D6005F3B3E /* RealmJSCoreTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RealmJSCoreTests.m; path = ios/RealmJSCoreTests.m; sourceTree = "<group>"; };
02414B871CE68CA200A8669F /* dates-v5.realm */ = {isa = PBXFileReference; lastKnownFileType = file; path = "dates-v5.realm"; sourceTree = "<group>"; }; 02414B871CE68CA200A8669F /* dates-v5.realm */ = {isa = PBXFileReference; lastKnownFileType = file; path = "dates-v5.realm"; sourceTree = "<group>"; };
02414B961CE6AADD00A8669F /* collection_notifications.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = collection_notifications.cpp; path = src/collection_notifications.cpp; sourceTree = "<group>"; }; 02414B961CE6AADD00A8669F /* collection_notifications.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = collection_notifications.cpp; path = src/collection_notifications.cpp; sourceTree = "<group>"; };
@ -110,11 +112,13 @@
02414B9E1CE6AAEF00A8669F /* list_notifier.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = list_notifier.hpp; sourceTree = "<group>"; }; 02414B9E1CE6AAEF00A8669F /* list_notifier.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = list_notifier.hpp; sourceTree = "<group>"; };
02414B9F1CE6AAEF00A8669F /* results_notifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = results_notifier.cpp; sourceTree = "<group>"; }; 02414B9F1CE6AAEF00A8669F /* results_notifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = results_notifier.cpp; sourceTree = "<group>"; };
02414BA01CE6AAEF00A8669F /* results_notifier.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = results_notifier.hpp; sourceTree = "<group>"; }; 02414BA01CE6AAEF00A8669F /* results_notifier.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = results_notifier.hpp; sourceTree = "<group>"; };
0250D9C01D7647E00012C20C /* js_sync.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = js_sync.hpp; sourceTree = "<group>"; };
025678951CAB392000FB8501 /* jsc_types.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = jsc_types.hpp; sourceTree = "<group>"; }; 025678951CAB392000FB8501 /* jsc_types.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = jsc_types.hpp; sourceTree = "<group>"; };
0270BC5A1B7CFC1300010E03 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 0270BC5A1B7CFC1300010E03 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
0270BC781B7D020100010E03 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = ios/Info.plist; sourceTree = "<group>"; }; 0270BC781B7D020100010E03 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = ios/Info.plist; sourceTree = "<group>"; };
0270BC7A1B7D020100010E03 /* RealmJSTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RealmJSTests.h; path = ios/RealmJSTests.h; sourceTree = "<group>"; }; 0270BC7A1B7D020100010E03 /* RealmJSTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RealmJSTests.h; path = ios/RealmJSTests.h; sourceTree = "<group>"; };
0270BC7B1B7D020100010E03 /* RealmJSTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RealmJSTests.mm; path = ios/RealmJSTests.mm; sourceTree = "<group>"; }; 0270BC7B1B7D020100010E03 /* RealmJSTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RealmJSTests.mm; path = ios/RealmJSTests.mm; sourceTree = "<group>"; };
02879D8B1DC29D5600777A5D /* package.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = package.json; path = ../package.json; sourceTree = "<group>"; };
029048011C0428DF00ABDED4 /* jsc_init.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = jsc_init.cpp; sourceTree = "<group>"; }; 029048011C0428DF00ABDED4 /* jsc_init.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = jsc_init.cpp; sourceTree = "<group>"; };
029048021C0428DF00ABDED4 /* jsc_init.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jsc_init.h; sourceTree = "<group>"; }; 029048021C0428DF00ABDED4 /* jsc_init.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jsc_init.h; sourceTree = "<group>"; };
029048041C0428DF00ABDED4 /* js_list.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = js_list.hpp; sourceTree = "<group>"; }; 029048041C0428DF00ABDED4 /* js_list.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = js_list.hpp; sourceTree = "<group>"; };
@ -127,13 +131,25 @@
029048101C0428DF00ABDED4 /* rpc.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = rpc.hpp; sourceTree = "<group>"; }; 029048101C0428DF00ABDED4 /* rpc.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = rpc.hpp; sourceTree = "<group>"; };
029048351C042A3C00ABDED4 /* platform.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = platform.hpp; sourceTree = "<group>"; }; 029048351C042A3C00ABDED4 /* platform.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = platform.hpp; sourceTree = "<group>"; };
029048381C042A8F00ABDED4 /* platform.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = platform.mm; sourceTree = "<group>"; }; 029048381C042A8F00ABDED4 /* platform.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = platform.mm; sourceTree = "<group>"; };
0290934A1CEFA9170009769E /* js_observable.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = js_observable.hpp; sourceTree = "<group>"; };
02A3C7A41BC4341500B1A7BE /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; }; 02A3C7A41BC4341500B1A7BE /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; };
02B58CBC1AE99CEC009B348C /* RealmJSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RealmJSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 02B58CBC1AE99CEC009B348C /* RealmJSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RealmJSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
02B58CCD1AE99D4D009B348C /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; 02B58CCD1AE99D4D009B348C /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
02D041F61CE11159000E4250 /* dates-v3.realm */ = {isa = PBXFileReference; lastKnownFileType = file; path = "dates-v3.realm"; sourceTree = "<group>"; }; 02D041F61CE11159000E4250 /* dates-v3.realm */ = {isa = PBXFileReference; lastKnownFileType = file; path = "dates-v3.realm"; sourceTree = "<group>"; };
02E008D11D10AB1B00F3AA37 /* atomic_shared_ptr.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = atomic_shared_ptr.hpp; sourceTree = "<group>"; }; 02E315C21DB80DDD00555337 /* sync_config.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = sync_config.hpp; path = src/sync/sync_config.hpp; sourceTree = "<group>"; };
02E008D21D10AB1B00F3AA37 /* format.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = format.cpp; sourceTree = "<group>"; }; 02E315C31DB80DDD00555337 /* sync_manager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sync_manager.cpp; path = src/sync/sync_manager.cpp; sourceTree = "<group>"; };
02E008D31D10AB1B00F3AA37 /* format.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = format.hpp; sourceTree = "<group>"; }; 02E315C41DB80DDD00555337 /* sync_manager.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = sync_manager.hpp; path = src/sync/sync_manager.hpp; sourceTree = "<group>"; };
02E315C51DB80DDD00555337 /* sync_session.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sync_session.cpp; path = src/sync/sync_session.cpp; sourceTree = "<group>"; };
02E315C61DB80DDD00555337 /* sync_session.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = sync_session.hpp; path = src/sync/sync_session.hpp; sourceTree = "<group>"; };
02E315C71DB80DDD00555337 /* sync_user.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sync_user.cpp; path = src/sync/sync_user.cpp; sourceTree = "<group>"; };
02E315C81DB80DDD00555337 /* sync_user.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = sync_user.hpp; path = src/sync/sync_user.hpp; sourceTree = "<group>"; };
02E315CD1DB80DF200555337 /* sync_client.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = sync_client.hpp; path = src/sync/impl/sync_client.hpp; sourceTree = "<group>"; };
02E315CE1DB80DF200555337 /* sync_file.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sync_file.cpp; path = src/sync/impl/sync_file.cpp; sourceTree = "<group>"; };
02E315CF1DB80DF200555337 /* sync_file.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = sync_file.hpp; path = src/sync/impl/sync_file.hpp; sourceTree = "<group>"; };
02E315D01DB80DF200555337 /* sync_metadata.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sync_metadata.cpp; path = src/sync/impl/sync_metadata.cpp; sourceTree = "<group>"; };
02E315D11DB80DF200555337 /* sync_metadata.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = sync_metadata.hpp; path = src/sync/impl/sync_metadata.hpp; sourceTree = "<group>"; };
02E315DE1DB8233E00555337 /* keychain_helper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = keychain_helper.cpp; sourceTree = "<group>"; };
02E315DF1DB8233E00555337 /* keychain_helper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = keychain_helper.hpp; sourceTree = "<group>"; };
02F59EAE1C88F17D007F774C /* binding_context.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = binding_context.hpp; path = src/binding_context.hpp; sourceTree = "<group>"; }; 02F59EAE1C88F17D007F774C /* binding_context.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = binding_context.hpp; path = src/binding_context.hpp; sourceTree = "<group>"; };
02F59EAF1C88F17D007F774C /* index_set.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = index_set.cpp; path = src/index_set.cpp; sourceTree = "<group>"; }; 02F59EAF1C88F17D007F774C /* index_set.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = index_set.cpp; path = src/index_set.cpp; sourceTree = "<group>"; };
02F59EB01C88F17D007F774C /* index_set.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = index_set.hpp; path = src/index_set.hpp; sourceTree = "<group>"; }; 02F59EB01C88F17D007F774C /* index_set.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = index_set.hpp; path = src/index_set.hpp; sourceTree = "<group>"; };
@ -151,26 +167,15 @@
02F59EBC1C88F17D007F774C /* schema.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = schema.hpp; path = src/schema.hpp; sourceTree = "<group>"; }; 02F59EBC1C88F17D007F774C /* schema.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = schema.hpp; path = src/schema.hpp; sourceTree = "<group>"; };
02F59EBD1C88F17D007F774C /* shared_realm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = shared_realm.cpp; path = src/shared_realm.cpp; sourceTree = "<group>"; }; 02F59EBD1C88F17D007F774C /* shared_realm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = shared_realm.cpp; path = src/shared_realm.cpp; sourceTree = "<group>"; };
02F59EBE1C88F17D007F774C /* shared_realm.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = shared_realm.hpp; path = src/shared_realm.hpp; sourceTree = "<group>"; }; 02F59EBE1C88F17D007F774C /* shared_realm.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = shared_realm.hpp; path = src/shared_realm.hpp; sourceTree = "<group>"; };
02F59EC61C88F190007F774C /* parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parser.cpp; sourceTree = "<group>"; };
02F59EC71C88F190007F774C /* parser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = parser.hpp; sourceTree = "<group>"; };
02F59EC81C88F190007F774C /* query_builder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = query_builder.cpp; sourceTree = "<group>"; };
02F59EC91C88F190007F774C /* query_builder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = query_builder.hpp; sourceTree = "<group>"; };
02F59ECF1C88F1B6007F774C /* external_commit_helper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = external_commit_helper.cpp; sourceTree = "<group>"; };
02F59ED01C88F1B6007F774C /* external_commit_helper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = external_commit_helper.hpp; sourceTree = "<group>"; };
02F59ED11C88F1B6007F774C /* weak_realm_notifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = weak_realm_notifier.cpp; sourceTree = "<group>"; };
02F59ED21C88F1B6007F774C /* weak_realm_notifier.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = weak_realm_notifier.hpp; sourceTree = "<group>"; };
02F59EDA1C88F2BA007F774C /* external_commit_helper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = external_commit_helper.hpp; sourceTree = "<group>"; }; 02F59EDA1C88F2BA007F774C /* external_commit_helper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = external_commit_helper.hpp; sourceTree = "<group>"; };
02F59EDB1C88F2BA007F774C /* realm_coordinator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = realm_coordinator.cpp; sourceTree = "<group>"; }; 02F59EDB1C88F2BA007F774C /* realm_coordinator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = realm_coordinator.cpp; sourceTree = "<group>"; };
02F59EDC1C88F2BB007F774C /* realm_coordinator.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = realm_coordinator.hpp; sourceTree = "<group>"; }; 02F59EDC1C88F2BB007F774C /* realm_coordinator.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = realm_coordinator.hpp; sourceTree = "<group>"; };
02F59EDD1C88F2BB007F774C /* transact_log_handler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = transact_log_handler.cpp; sourceTree = "<group>"; }; 02F59EDD1C88F2BB007F774C /* transact_log_handler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = transact_log_handler.cpp; sourceTree = "<group>"; };
02F59EDE1C88F2BB007F774C /* transact_log_handler.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = transact_log_handler.hpp; sourceTree = "<group>"; }; 02F59EDE1C88F2BB007F774C /* transact_log_handler.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = transact_log_handler.hpp; sourceTree = "<group>"; };
02F59EDF1C88F2BB007F774C /* weak_realm_notifier_base.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = weak_realm_notifier_base.hpp; sourceTree = "<group>"; };
02F59EE01C88F2BB007F774C /* weak_realm_notifier.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = weak_realm_notifier.hpp; sourceTree = "<group>"; };
5DC74A721D623C7A00D77A4F /* thread_confined.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = thread_confined.cpp; path = src/thread_confined.cpp; sourceTree = "<group>"; }; 5DC74A721D623C7A00D77A4F /* thread_confined.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = thread_confined.cpp; path = src/thread_confined.cpp; sourceTree = "<group>"; };
5DC74A731D623C7A00D77A4F /* thread_confined.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = thread_confined.hpp; path = src/thread_confined.hpp; sourceTree = "<group>"; }; 5DC74A731D623C7A00D77A4F /* thread_confined.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = thread_confined.hpp; path = src/thread_confined.hpp; sourceTree = "<group>"; };
5DC74A751D623C8700D77A4F /* handover.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = handover.cpp; sourceTree = "<group>"; }; 5DC74A751D623C8700D77A4F /* handover.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = handover.cpp; sourceTree = "<group>"; };
5DC74A761D623C8700D77A4F /* handover.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = handover.hpp; sourceTree = "<group>"; }; 5DC74A761D623C8700D77A4F /* handover.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = handover.hpp; sourceTree = "<group>"; };
5DC74A7C1D623CED00D77A4F /* compiler.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = compiler.hpp; sourceTree = "<group>"; };
F60102CF1CBB814A00EC01BA /* node_init.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = node_init.hpp; sourceTree = "<group>"; }; F60102CF1CBB814A00EC01BA /* node_init.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = node_init.hpp; sourceTree = "<group>"; };
F60102D11CBB865A00EC01BA /* jsc_init.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = jsc_init.hpp; sourceTree = "<group>"; }; F60102D11CBB865A00EC01BA /* jsc_init.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = jsc_init.hpp; sourceTree = "<group>"; };
F60102E31CBBB19700EC01BA /* node_object_accessor.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = node_object_accessor.hpp; sourceTree = "<group>"; }; F60102E31CBBB19700EC01BA /* node_object_accessor.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = node_object_accessor.hpp; sourceTree = "<group>"; };
@ -200,19 +205,12 @@
F620F0571CB766DA0082977B /* node_init.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = node_init.cpp; sourceTree = "<group>"; }; F620F0571CB766DA0082977B /* node_init.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = node_init.cpp; sourceTree = "<group>"; };
F620F0591CB7B4C80082977B /* js_object_accessor.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = js_object_accessor.hpp; sourceTree = "<group>"; }; F620F0591CB7B4C80082977B /* js_object_accessor.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = js_object_accessor.hpp; sourceTree = "<group>"; };
F620F0741CB9F60C0082977B /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/CoreFoundation.framework; sourceTree = DEVELOPER_DIR; }; F620F0741CB9F60C0082977B /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/CoreFoundation.framework; sourceTree = DEVELOPER_DIR; };
F6242B291D08EE9600BE1E03 /* thread_id.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = thread_id.hpp; sourceTree = "<group>"; };
F6267BC91CADC30000AC36B1 /* js_util.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = js_util.hpp; sourceTree = "<group>"; }; F6267BC91CADC30000AC36B1 /* js_util.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = js_util.hpp; sourceTree = "<group>"; };
F6267BCA1CADC49200AC36B1 /* node_dummy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = node_dummy.cpp; sourceTree = "<group>"; }; F6267BCA1CADC49200AC36B1 /* node_dummy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = node_dummy.cpp; sourceTree = "<group>"; };
F62BF8FB1CAC71780022BCDC /* libRealmNode.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libRealmNode.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
F63117EE1CEB0D5900ECB2DE /* weak_realm_notifier.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = weak_realm_notifier.cpp; sourceTree = "<group>"; };
F63117EF1CEB0D5900ECB2DE /* weak_realm_notifier.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = weak_realm_notifier.hpp; sourceTree = "<group>"; };
F63118431CEBA7B700ECB2DE /* external_commit_helper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = external_commit_helper.cpp; sourceTree = "<group>"; }; F63118431CEBA7B700ECB2DE /* external_commit_helper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = external_commit_helper.cpp; sourceTree = "<group>"; };
F63118441CEBA7B700ECB2DE /* external_commit_helper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = external_commit_helper.hpp; sourceTree = "<group>"; }; F63118441CEBA7B700ECB2DE /* external_commit_helper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = external_commit_helper.hpp; sourceTree = "<group>"; };
F63118451CEBA7B700ECB2DE /* weak_realm_notifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = weak_realm_notifier.cpp; sourceTree = "<group>"; };
F63118461CEBA7B700ECB2DE /* weak_realm_notifier.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = weak_realm_notifier.hpp; sourceTree = "<group>"; };
F631184A1CEBA7D800ECB2DE /* external_commit_helper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = external_commit_helper.cpp; sourceTree = "<group>"; }; F631184A1CEBA7D800ECB2DE /* external_commit_helper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = external_commit_helper.cpp; sourceTree = "<group>"; };
F631184B1CEBA7D800ECB2DE /* external_commit_helper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = external_commit_helper.hpp; sourceTree = "<group>"; }; F631184B1CEBA7D800ECB2DE /* external_commit_helper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = external_commit_helper.hpp; sourceTree = "<group>"; };
F631184C1CEBA7D800ECB2DE /* weak_realm_notifier.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = weak_realm_notifier.hpp; sourceTree = "<group>"; };
F63FF2B11C1241E500B3B8E0 /* libRealmJS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRealmJS.a; sourceTree = BUILT_PRODUCTS_DIR; }; F63FF2B11C1241E500B3B8E0 /* libRealmJS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRealmJS.a; sourceTree = BUILT_PRODUCTS_DIR; };
F63FF2F01C16405C00B3B8E0 /* libGCDWebServers.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libGCDWebServers.a; sourceTree = BUILT_PRODUCTS_DIR; }; F63FF2F01C16405C00B3B8E0 /* libGCDWebServers.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libGCDWebServers.a; sourceTree = BUILT_PRODUCTS_DIR; };
F63FF2FD1C1642BB00B3B8E0 /* GCDWebServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDWebServer.h; sourceTree = "<group>"; }; F63FF2FD1C1642BB00B3B8E0 /* GCDWebServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDWebServer.h; sourceTree = "<group>"; };
@ -248,8 +246,6 @@
F63FF32C1C16432E00B3B8E0 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; F63FF32C1C16432E00B3B8E0 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };
F63FF32E1C16433900B3B8E0 /* libxml2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libxml2.tbd; path = usr/lib/libxml2.tbd; sourceTree = SDKROOT; }; F63FF32E1C16433900B3B8E0 /* libxml2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libxml2.tbd; path = usr/lib/libxml2.tbd; sourceTree = SDKROOT; };
F63FF3301C16434400B3B8E0 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; F63FF3301C16434400B3B8E0 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
F64A059C1D13710C004ACDBE /* thread_id.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thread_id.cpp; sourceTree = "<group>"; };
F64A059F1D13716B004ACDBE /* thread_local.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = thread_local.hpp; sourceTree = "<group>"; };
F67478481CC81F1300F9273C /* platform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = platform.cpp; sourceTree = "<group>"; }; F67478481CC81F1300F9273C /* platform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = platform.cpp; sourceTree = "<group>"; };
F6874A351CAC792D00EEEE36 /* node_types.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = node_types.hpp; sourceTree = "<group>"; }; F6874A351CAC792D00EEEE36 /* node_types.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = node_types.hpp; sourceTree = "<group>"; };
F6874A3E1CACA5A900EEEE36 /* js_types.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = js_types.hpp; sourceTree = "<group>"; }; F6874A3E1CACA5A900EEEE36 /* js_types.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = js_types.hpp; sourceTree = "<group>"; };
@ -266,19 +262,12 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
5D25F5A11D6284FD00EBBB30 /* libz.tbd in Frameworks */,
027A23131CD3E379000543AE /* libRealmJS.a in Frameworks */, 027A23131CD3E379000543AE /* libRealmJS.a in Frameworks */,
02D8D1F71B601984006DB49D /* JavaScriptCore.framework in Frameworks */, 02D8D1F71B601984006DB49D /* JavaScriptCore.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
F62BF8F81CAC71780022BCDC /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
F620F0751CB9F60C0082977B /* CoreFoundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
F63FF2ED1C16405C00B3B8E0 /* Frameworks */ = { F63FF2ED1C16405C00B3B8E0 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
@ -289,19 +278,74 @@
/* End PBXFrameworksBuildPhase section */ /* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */ /* Begin PBXGroup section */
02022A6B1DA47EC8000F0C4F /* util */ = {
isa = PBXGroup;
children = (
02022A6C1DA47EC8000F0C4F /* android */,
02022A6E1DA47EC8000F0C4F /* apple */,
02022A701DA47EC8000F0C4F /* atomic_shared_ptr.hpp */,
02022A711DA47EC8000F0C4F /* compiler.hpp */,
02022A721DA47EC8000F0C4F /* event_loop_signal.hpp */,
02022A731DA47EC8000F0C4F /* format.cpp */,
02022A741DA47EC8000F0C4F /* format.hpp */,
02022A751DA47EC8000F0C4F /* generic */,
02022A771DA47EC8000F0C4F /* node */,
02022A791DA47EC8000F0C4F /* thread_id.cpp */,
02022A7A1DA47EC8000F0C4F /* thread_id.hpp */,
02022A7B1DA47EC8000F0C4F /* thread_local.hpp */,
);
name = util;
path = src/util;
sourceTree = "<group>";
};
02022A6C1DA47EC8000F0C4F /* android */ = {
isa = PBXGroup;
children = (
02022A6D1DA47EC8000F0C4F /* event_loop_signal.hpp */,
);
path = android;
sourceTree = "<group>";
};
02022A6E1DA47EC8000F0C4F /* apple */ = {
isa = PBXGroup;
children = (
02022A6F1DA47EC8000F0C4F /* event_loop_signal.hpp */,
);
path = apple;
sourceTree = "<group>";
};
02022A751DA47EC8000F0C4F /* generic */ = {
isa = PBXGroup;
children = (
02022A761DA47EC8000F0C4F /* event_loop_signal.hpp */,
);
path = generic;
sourceTree = "<group>";
};
02022A771DA47EC8000F0C4F /* node */ = {
isa = PBXGroup;
children = (
02022A781DA47EC8000F0C4F /* event_loop_signal.hpp */,
);
path = node;
sourceTree = "<group>";
};
0270BC3D1B7CFBFD00010E03 /* RealmJS */ = { 0270BC3D1B7CFBFD00010E03 /* RealmJS */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
F6BCCFDF1C83809A00FE31AE /* lib */, F6BCCFDF1C83809A00FE31AE /* lib */,
02879D8B1DC29D5600777A5D /* package.json */,
F62A35131C18E6E2004A917D /* iOS */, F62A35131C18E6E2004A917D /* iOS */,
F6874A441CAD2ACD00EEEE36 /* JSC */, F6874A441CAD2ACD00EEEE36 /* JSC */,
F62BF9001CAC72C40022BCDC /* Node */, F62BF9001CAC72C40022BCDC /* Node */,
F62A35141C18E783004A917D /* Object Store */, F62A35141C18E783004A917D /* Object Store */,
0290934A1CEFA9170009769E /* js_observable.hpp */,
F60102F71CBDA6D400EC01BA /* js_collection.hpp */, F60102F71CBDA6D400EC01BA /* js_collection.hpp */,
029048041C0428DF00ABDED4 /* js_list.hpp */, 029048041C0428DF00ABDED4 /* js_list.hpp */,
029048061C0428DF00ABDED4 /* js_realm_object.hpp */, 029048061C0428DF00ABDED4 /* js_realm_object.hpp */,
029048071C0428DF00ABDED4 /* js_realm.cpp */, 029048071C0428DF00ABDED4 /* js_realm.cpp */,
029048081C0428DF00ABDED4 /* js_realm.hpp */, 029048081C0428DF00ABDED4 /* js_realm.hpp */,
0250D9C01D7647E00012C20C /* js_sync.hpp */,
0290480A1C0428DF00ABDED4 /* js_results.hpp */, 0290480A1C0428DF00ABDED4 /* js_results.hpp */,
0290480C1C0428DF00ABDED4 /* js_schema.hpp */, 0290480C1C0428DF00ABDED4 /* js_schema.hpp */,
F620F0521CAF0B600082977B /* js_class.hpp */, F620F0521CAF0B600082977B /* js_class.hpp */,
@ -333,7 +377,6 @@
02B58CBC1AE99CEC009B348C /* RealmJSTests.xctest */, 02B58CBC1AE99CEC009B348C /* RealmJSTests.xctest */,
F63FF2B11C1241E500B3B8E0 /* libRealmJS.a */, F63FF2B11C1241E500B3B8E0 /* libRealmJS.a */,
F63FF2F01C16405C00B3B8E0 /* libGCDWebServers.a */, F63FF2F01C16405C00B3B8E0 /* libGCDWebServers.a */,
F62BF8FB1CAC71780022BCDC /* libRealmNode.dylib */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@ -378,19 +421,23 @@
path = data; path = data;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
02E008D01D10AB1B00F3AA37 /* util */ = { 02E315CC1DB80DE000555337 /* sync */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
02E008D11D10AB1B00F3AA37 /* atomic_shared_ptr.hpp */, 02E315CD1DB80DF200555337 /* sync_client.hpp */,
5DC74A7C1D623CED00D77A4F /* compiler.hpp */, 02E315CE1DB80DF200555337 /* sync_file.cpp */,
02E008D21D10AB1B00F3AA37 /* format.cpp */, 02E315CF1DB80DF200555337 /* sync_file.hpp */,
02E008D31D10AB1B00F3AA37 /* format.hpp */, 02E315D01DB80DF200555337 /* sync_metadata.cpp */,
F6242B291D08EE9600BE1E03 /* thread_id.hpp */, 02E315D11DB80DF200555337 /* sync_metadata.hpp */,
F64A059C1D13710C004ACDBE /* thread_id.cpp */, 02E315C21DB80DDD00555337 /* sync_config.hpp */,
F64A059F1D13716B004ACDBE /* thread_local.hpp */, 02E315C31DB80DDD00555337 /* sync_manager.cpp */,
02E315C41DB80DDD00555337 /* sync_manager.hpp */,
02E315C51DB80DDD00555337 /* sync_session.cpp */,
02E315C61DB80DDD00555337 /* sync_session.hpp */,
02E315C71DB80DDD00555337 /* sync_user.cpp */,
02E315C81DB80DDD00555337 /* sync_user.hpp */,
); );
name = util; name = sync;
path = src/util;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
F62A35131C18E6E2004A917D /* iOS */ = { F62A35131C18E6E2004A917D /* iOS */ = {
@ -406,7 +453,8 @@
F62A35141C18E783004A917D /* Object Store */ = { F62A35141C18E783004A917D /* Object Store */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
02E008D01D10AB1B00F3AA37 /* util */, 02E315CC1DB80DE000555337 /* sync */,
02022A6B1DA47EC8000F0C4F /* util */,
F63117EA1CEB0BFA00ECB2DE /* impl */, F63117EA1CEB0BFA00ECB2DE /* impl */,
F63117EC1CEB0C8100ECB2DE /* parser */, F63117EC1CEB0C8100ECB2DE /* parser */,
02414B961CE6AADD00A8669F /* collection_notifications.cpp */, 02414B961CE6AADD00A8669F /* collection_notifications.cpp */,
@ -421,6 +469,7 @@
02F59EB51C88F17D007F774C /* object_schema.hpp */, 02F59EB51C88F17D007F774C /* object_schema.hpp */,
02F59EB61C88F17D007F774C /* object_store.cpp */, 02F59EB61C88F17D007F774C /* object_store.cpp */,
02F59EB71C88F17D007F774C /* object_store.hpp */, 02F59EB71C88F17D007F774C /* object_store.hpp */,
02022A4C1DA475C0000F0C4F /* placeholder.cpp */,
02F59EB81C88F17D007F774C /* property.hpp */, 02F59EB81C88F17D007F774C /* property.hpp */,
02F59EB91C88F17D007F774C /* results.cpp */, 02F59EB91C88F17D007F774C /* results.cpp */,
02F59EBA1C88F17D007F774C /* results.hpp */, 02F59EBA1C88F17D007F774C /* results.hpp */,
@ -464,7 +513,6 @@
F63118421CEBA7A100ECB2DE /* android */, F63118421CEBA7A100ECB2DE /* android */,
F63117EB1CEB0C1B00ECB2DE /* apple */, F63117EB1CEB0C1B00ECB2DE /* apple */,
F63118491CEBA7BD00ECB2DE /* generic */, F63118491CEBA7BD00ECB2DE /* generic */,
F63117ED1CEB0CC600ECB2DE /* node */,
02414B991CE6AAEF00A8669F /* collection_change_builder.cpp */, 02414B991CE6AAEF00A8669F /* collection_change_builder.cpp */,
02414B9A1CE6AAEF00A8669F /* collection_change_builder.hpp */, 02414B9A1CE6AAEF00A8669F /* collection_change_builder.hpp */,
02414B9B1CE6AAEF00A8669F /* collection_notifier.cpp */, 02414B9B1CE6AAEF00A8669F /* collection_notifier.cpp */,
@ -480,8 +528,8 @@
02F59EDC1C88F2BB007F774C /* realm_coordinator.hpp */, 02F59EDC1C88F2BB007F774C /* realm_coordinator.hpp */,
02F59EDD1C88F2BB007F774C /* transact_log_handler.cpp */, 02F59EDD1C88F2BB007F774C /* transact_log_handler.cpp */,
02F59EDE1C88F2BB007F774C /* transact_log_handler.hpp */, 02F59EDE1C88F2BB007F774C /* transact_log_handler.hpp */,
02F59EDF1C88F2BB007F774C /* weak_realm_notifier_base.hpp */, 02022A481DA474A7000F0C4F /* weak_realm_notifier.hpp */,
02F59EE01C88F2BB007F774C /* weak_realm_notifier.hpp */, 02022A4A1DA475A9000F0C4F /* weak_realm_notifier.cpp */,
); );
name = impl; name = impl;
path = src/impl; path = src/impl;
@ -490,10 +538,10 @@
F63117EB1CEB0C1B00ECB2DE /* apple */ = { F63117EB1CEB0C1B00ECB2DE /* apple */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
02F59ECF1C88F1B6007F774C /* external_commit_helper.cpp */, 02E315DE1DB8233E00555337 /* keychain_helper.cpp */,
02F59ED01C88F1B6007F774C /* external_commit_helper.hpp */, 02E315DF1DB8233E00555337 /* keychain_helper.hpp */,
02F59ED11C88F1B6007F774C /* weak_realm_notifier.cpp */, 02022A411DA47489000F0C4F /* external_commit_helper.cpp */,
02F59ED21C88F1B6007F774C /* weak_realm_notifier.hpp */, 02022A421DA47489000F0C4F /* external_commit_helper.hpp */,
); );
path = apple; path = apple;
sourceTree = "<group>"; sourceTree = "<group>";
@ -501,31 +549,20 @@
F63117EC1CEB0C8100ECB2DE /* parser */ = { F63117EC1CEB0C8100ECB2DE /* parser */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
02F59EC61C88F190007F774C /* parser.cpp */, 02022A611DA47B8B000F0C4F /* parser.cpp */,
02F59EC71C88F190007F774C /* parser.hpp */, 02022A621DA47B8B000F0C4F /* parser.hpp */,
02F59EC81C88F190007F774C /* query_builder.cpp */, 02022A631DA47B8B000F0C4F /* query_builder.cpp */,
02F59EC91C88F190007F774C /* query_builder.hpp */, 02022A641DA47B8B000F0C4F /* query_builder.hpp */,
); );
name = parser; name = parser;
path = src/parser; path = src/parser;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
F63117ED1CEB0CC600ECB2DE /* node */ = {
isa = PBXGroup;
children = (
F63117EE1CEB0D5900ECB2DE /* weak_realm_notifier.cpp */,
F63117EF1CEB0D5900ECB2DE /* weak_realm_notifier.hpp */,
);
path = node;
sourceTree = "<group>";
};
F63118421CEBA7A100ECB2DE /* android */ = { F63118421CEBA7A100ECB2DE /* android */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
F63118431CEBA7B700ECB2DE /* external_commit_helper.cpp */, F63118431CEBA7B700ECB2DE /* external_commit_helper.cpp */,
F63118441CEBA7B700ECB2DE /* external_commit_helper.hpp */, F63118441CEBA7B700ECB2DE /* external_commit_helper.hpp */,
F63118451CEBA7B700ECB2DE /* weak_realm_notifier.cpp */,
F63118461CEBA7B700ECB2DE /* weak_realm_notifier.hpp */,
); );
path = android; path = android;
sourceTree = "<group>"; sourceTree = "<group>";
@ -535,7 +572,6 @@
children = ( children = (
F631184A1CEBA7D800ECB2DE /* external_commit_helper.cpp */, F631184A1CEBA7D800ECB2DE /* external_commit_helper.cpp */,
F631184B1CEBA7D800ECB2DE /* external_commit_helper.hpp */, F631184B1CEBA7D800ECB2DE /* external_commit_helper.hpp */,
F631184C1CEBA7D800ECB2DE /* weak_realm_notifier.hpp */,
); );
path = generic; path = generic;
sourceTree = "<group>"; sourceTree = "<group>";
@ -644,7 +680,7 @@
02B58CB81AE99CEC009B348C /* Sources */, 02B58CB81AE99CEC009B348C /* Sources */,
02B58CB91AE99CEC009B348C /* Frameworks */, 02B58CB91AE99CEC009B348C /* Frameworks */,
02B58CBA1AE99CEC009B348C /* Resources */, 02B58CBA1AE99CEC009B348C /* Resources */,
F613787A1C18F003008BFC51 /* Copy Query Tests */, 02879D8D1DC29F2000777A5D /* Install Node Modules */,
); );
buildRules = ( buildRules = (
); );
@ -655,24 +691,6 @@
productReference = 02B58CBC1AE99CEC009B348C /* RealmJSTests.xctest */; productReference = 02B58CBC1AE99CEC009B348C /* RealmJSTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test"; productType = "com.apple.product-type.bundle.unit-test";
}; };
F62BF8FA1CAC71780022BCDC /* RealmNode */ = {
isa = PBXNativeTarget;
buildConfigurationList = F62BF8FF1CAC71780022BCDC /* Build configuration list for PBXNativeTarget "RealmNode" */;
buildPhases = (
F64A05B71D140311004ACDBE /* Download Core */,
F62BF8F71CAC71780022BCDC /* Sources */,
F62BF8F81CAC71780022BCDC /* Frameworks */,
F63117A41CEA911000ECB2DE /* Build with node-gyp */,
);
buildRules = (
);
dependencies = (
);
name = RealmNode;
productName = RealmNode;
productReference = F62BF8FB1CAC71780022BCDC /* libRealmNode.dylib */;
productType = "com.apple.product-type.library.dynamic";
};
F63FF2B01C1241E500B3B8E0 /* RealmJS */ = { F63FF2B01C1241E500B3B8E0 /* RealmJS */ = {
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = F63FF2C41C1241E500B3B8E0 /* Build configuration list for PBXNativeTarget "RealmJS" */; buildConfigurationList = F63FF2C41C1241E500B3B8E0 /* Build configuration list for PBXNativeTarget "RealmJS" */;
@ -718,9 +736,6 @@
02B58CBB1AE99CEC009B348C = { 02B58CBB1AE99CEC009B348C = {
CreatedOnToolsVersion = 6.3.1; CreatedOnToolsVersion = 6.3.1;
}; };
F62BF8FA1CAC71780022BCDC = {
CreatedOnToolsVersion = 7.3;
};
F63FF2B01C1241E500B3B8E0 = { F63FF2B01C1241E500B3B8E0 = {
CreatedOnToolsVersion = 7.1.1; CreatedOnToolsVersion = 7.1.1;
}; };
@ -743,7 +758,6 @@
targets = ( targets = (
F63FF2EF1C16405C00B3B8E0 /* GCDWebServers */, F63FF2EF1C16405C00B3B8E0 /* GCDWebServers */,
F63FF2B01C1241E500B3B8E0 /* RealmJS */, F63FF2B01C1241E500B3B8E0 /* RealmJS */,
F62BF8FA1CAC71780022BCDC /* RealmNode */,
02B58CBB1AE99CEC009B348C /* RealmJSTests */, 02B58CBB1AE99CEC009B348C /* RealmJSTests */,
); );
}; };
@ -764,33 +778,19 @@
/* End PBXResourcesBuildPhase section */ /* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */
F613787A1C18F003008BFC51 /* Copy Query Tests */ = { 02879D8D1DC29F2000777A5D /* Install Node Modules */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
); );
inputPaths = ( inputPaths = (
); );
name = "Copy Query Tests"; name = "Install Node Modules";
outputPaths = ( outputPaths = (
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "DEST=\"$TARGET_BUILD_DIR/$CONTENTS_FOLDER_PATH/js/query-tests.json\"\nrm -f \"$DEST\"\ncp object-store/tests/query.json \"$DEST\""; shellScript = "cd \"$TARGET_BUILD_DIR/$CONTENTS_FOLDER_PATH\"\nyarn add needle url-parse";
};
F63117A41CEA911000ECB2DE /* Build with node-gyp */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Build with node-gyp";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "node/build-node.sh \"$CONFIGURATION\"";
}; };
F63FF2C51C12462600B3B8E0 /* Download Core */ = { F63FF2C51C12462600B3B8E0 /* Download Core */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
@ -806,20 +806,6 @@
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "../scripts/download-core.sh"; shellScript = "../scripts/download-core.sh";
}; };
F64A05B71D140311004ACDBE /* Download Core */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Download Core";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "../scripts/download-core.sh node";
};
/* End PBXShellScriptBuildPhase section */ /* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */
@ -833,70 +819,44 @@
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
F62BF8F71CAC71780022BCDC /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F6E931BA1CFEAE170016AF14 /* collection_notifications.cpp in Sources */,
F60102D31CBB966E00EC01BA /* js_realm.cpp in Sources */,
F60102D61CBB96B400EC01BA /* object_schema.cpp in Sources */,
F60102D41CBB96AB00EC01BA /* index_set.cpp in Sources */,
F60102DB1CBB96C600EC01BA /* parser.cpp in Sources */,
F6E931BB1CFEAE310016AF14 /* collection_change_builder.cpp in Sources */,
F64A059B1D10D928004ACDBE /* format.cpp in Sources */,
5DC74A7B1D623CA800D77A4F /* thread_confined.cpp in Sources */,
F60102D51CBB96AE00EC01BA /* list.cpp in Sources */,
F6E931BC1CFEAE340016AF14 /* collection_notifier.cpp in Sources */,
F60102DC1CBB96C900EC01BA /* query_builder.cpp in Sources */,
F60102DD1CBB96CC00EC01BA /* external_commit_helper.cpp in Sources */,
F63117F01CEB0D5F00ECB2DE /* weak_realm_notifier.cpp in Sources */,
F60102E11CBB96DD00EC01BA /* transact_log_handler.cpp in Sources */,
F6E931BE1CFEAE3A0016AF14 /* results_notifier.cpp in Sources */,
F60102D71CBB96B800EC01BA /* object_store.cpp in Sources */,
F6E931BD1CFEAE370016AF14 /* list_notifier.cpp in Sources */,
F60102DA1CBB96C300EC01BA /* shared_realm.cpp in Sources */,
F60102E01CBB96D900EC01BA /* realm_coordinator.cpp in Sources */,
F64A059E1D13710C004ACDBE /* thread_id.cpp in Sources */,
F60102EA1CBCAFC300EC01BA /* node_dummy.cpp in Sources */,
F60102D81CBB96BD00EC01BA /* results.cpp in Sources */,
F674784A1CC81F1900F9273C /* platform.cpp in Sources */,
F620F0581CB766DA0082977B /* node_init.cpp in Sources */,
5DC74A791D623CA200D77A4F /* handover.cpp in Sources */,
F60102D91CBB96C100EC01BA /* schema.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
F63FF2AD1C1241E500B3B8E0 /* Sources */ = { F63FF2AD1C1241E500B3B8E0 /* Sources */ = {
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
02E008D51D10ABB600F3AA37 /* format.cpp in Sources */, 02E315C91DB80DDD00555337 /* sync_manager.cpp in Sources */,
02022A671DA47BD7000F0C4F /* parser.cpp in Sources */,
02022A681DA47BD7000F0C4F /* query_builder.cpp in Sources */,
02E315E01DB8233E00555337 /* keychain_helper.cpp in Sources */,
02022A581DA476CD000F0C4F /* external_commit_helper.cpp in Sources */,
02022A5A1DA476CD000F0C4F /* weak_realm_notifier.cpp in Sources */,
02022A5B1DA476CD000F0C4F /* placeholder.cpp in Sources */,
5DC74A7A1D623CA800D77A4F /* thread_confined.cpp in Sources */, 5DC74A7A1D623CA800D77A4F /* thread_confined.cpp in Sources */,
02414BA51CE6ABCF00A8669F /* collection_change_builder.cpp in Sources */, 02414BA51CE6ABCF00A8669F /* collection_change_builder.cpp in Sources */,
02414BA61CE6ABCF00A8669F /* collection_notifier.cpp in Sources */, 02414BA61CE6ABCF00A8669F /* collection_notifier.cpp in Sources */,
F64A059D1D13710C004ACDBE /* thread_id.cpp in Sources */,
02414BA71CE6ABCF00A8669F /* list_notifier.cpp in Sources */, 02414BA71CE6ABCF00A8669F /* list_notifier.cpp in Sources */,
02414BA81CE6ABCF00A8669F /* results_notifier.cpp in Sources */, 02414BA81CE6ABCF00A8669F /* results_notifier.cpp in Sources */,
02414BA91CE6ABCF00A8669F /* collection_notifications.cpp in Sources */, 02414BA91CE6ABCF00A8669F /* collection_notifications.cpp in Sources */,
02F59EE31C88F2BB007F774C /* transact_log_handler.cpp in Sources */, 02F59EE31C88F2BB007F774C /* transact_log_handler.cpp in Sources */,
5DC74A781D623C9800D77A4F /* handover.cpp in Sources */, 5DC74A781D623C9800D77A4F /* handover.cpp in Sources */,
F63FF2E81C159C4B00B3B8E0 /* platform.mm in Sources */, F63FF2E81C159C4B00B3B8E0 /* platform.mm in Sources */,
02E315CA1DB80DDD00555337 /* sync_session.cpp in Sources */,
02F59EC31C88F17D007F774C /* results.cpp in Sources */, 02F59EC31C88F17D007F774C /* results.cpp in Sources */,
F63FF2E21C15921A00B3B8E0 /* base64.cpp in Sources */, F63FF2E21C15921A00B3B8E0 /* base64.cpp in Sources */,
F63FF2C61C12469E00B3B8E0 /* jsc_init.cpp in Sources */, F63FF2C61C12469E00B3B8E0 /* jsc_init.cpp in Sources */,
02F59ECA1C88F190007F774C /* parser.cpp in Sources */,
02F59EC01C88F17D007F774C /* list.cpp in Sources */, 02F59EC01C88F17D007F774C /* list.cpp in Sources */,
02F59EBF1C88F17D007F774C /* index_set.cpp in Sources */, 02F59EBF1C88F17D007F774C /* index_set.cpp in Sources */,
02F59ED51C88F1B6007F774C /* weak_realm_notifier.cpp in Sources */,
F63FF2C91C12469E00B3B8E0 /* js_realm.cpp in Sources */, F63FF2C91C12469E00B3B8E0 /* js_realm.cpp in Sources */,
02F59EC51C88F17D007F774C /* shared_realm.cpp in Sources */, 02F59EC51C88F17D007F774C /* shared_realm.cpp in Sources */,
02F59ECB1C88F190007F774C /* query_builder.cpp in Sources */,
02F59EE21C88F2BB007F774C /* realm_coordinator.cpp in Sources */, 02F59EE21C88F2BB007F774C /* realm_coordinator.cpp in Sources */,
02F59EC41C88F17D007F774C /* schema.cpp in Sources */, 02F59EC41C88F17D007F774C /* schema.cpp in Sources */,
F63FF2CD1C12469E00B3B8E0 /* rpc.cpp in Sources */, F63FF2CD1C12469E00B3B8E0 /* rpc.cpp in Sources */,
02E315D21DB80DF200555337 /* sync_file.cpp in Sources */,
02F59EC21C88F17D007F774C /* object_store.cpp in Sources */, 02F59EC21C88F17D007F774C /* object_store.cpp in Sources */,
02022A7C1DA47EC8000F0C4F /* format.cpp in Sources */,
02022A7D1DA47EC8000F0C4F /* thread_id.cpp in Sources */,
02E315CB1DB80DDD00555337 /* sync_user.cpp in Sources */,
02E315D31DB80DF200555337 /* sync_metadata.cpp in Sources */,
02F59EC11C88F17D007F774C /* object_schema.cpp in Sources */, 02F59EC11C88F17D007F774C /* object_schema.cpp in Sources */,
02F59ED41C88F1B6007F774C /* external_commit_helper.cpp in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -927,6 +887,7 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
CC = "$(SRCROOT)/../scripts/ccache-clang.sh";
CLANG_CXX_LANGUAGE_STANDARD = "c++14"; CLANG_CXX_LANGUAGE_STANDARD = "c++14";
CLANG_CXX_LIBRARY = "libc++"; CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
@ -942,7 +903,8 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 0.14.3; CURRENT_PROJECT_VERSION = 0.15.0;
CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh";
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES; ENABLE_TESTABILITY = YES;
@ -988,6 +950,7 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
CC = "$(SRCROOT)/../scripts/ccache-clang.sh";
CLANG_CXX_LANGUAGE_STANDARD = "c++14"; CLANG_CXX_LANGUAGE_STANDARD = "c++14";
CLANG_CXX_LIBRARY = "libc++"; CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
@ -1003,7 +966,8 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 0.14.3; CURRENT_PROJECT_VERSION = 0.15.0;
CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh";
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
@ -1072,85 +1036,25 @@
}; };
name = Release; name = Release;
}; };
F62BF8FC1CAC71780022BCDC /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
DEBUG_INFORMATION_FORMAT = dwarf;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 0.14.3;
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 = (
/usr/local/lib,
"../core-node",
);
OTHER_CPLUSPLUSFLAGS = (
"$(inherited)",
"-isystem",
"../core-node/include",
);
OTHER_LDFLAGS = (
"-lrealm-node-dbg",
"-luv",
"-lv8",
);
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
};
name = Debug;
};
F62BF8FE1CAC71780022BCDC /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 0.14.3;
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 = (
/usr/local/lib,
"../core-node",
);
OTHER_CPLUSPLUSFLAGS = (
"$(inherited)",
"-isystem",
"../core-node/include",
);
OTHER_LDFLAGS = (
"-lrealm-node",
"-luv",
"-lv8",
);
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
};
name = Release;
};
F63FF2B71C1241E500B3B8E0 /* Debug */ = { F63FF2B71C1241E500B3B8E0 /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
DEBUG_INFORMATION_FORMAT = dwarf; DEBUG_INFORMATION_FORMAT = dwarf;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
REALM_DEBUG,
REALM_HAVE_CONFIG,
__ASSERTMACROS__,
REALM_ENABLE_SYNC,
);
OTHER_CPLUSPLUSFLAGS = ( OTHER_CPLUSPLUSFLAGS = (
"$(inherited)", "$(inherited)",
"-isystem", "-isystem",
../core/include, "$(SRCROOT)/../vendor/core/include",
"-isystem",
"$(SRCROOT)/../vendor/sync/include",
); );
OTHER_LIBTOOLFLAGS = "$(SRCROOT)/../core/librealm-ios-dbg.a"; OTHER_LIBTOOLFLAGS = "$(SRCROOT)/../vendor/core/librealm-ios-dbg.a $(SRCROOT)/../vendor/sync/librealm-ios-dbg.a";
PRODUCT_NAME = RealmJS; PRODUCT_NAME = RealmJS;
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
}; };
@ -1159,12 +1063,19 @@
F63FF2B91C1241E500B3B8E0 /* Release */ = { F63FF2B91C1241E500B3B8E0 /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
GCC_PREPROCESSOR_DEFINITIONS = (
REALM_HAVE_CONFIG,
__ASSERTMACROS__,
REALM_ENABLE_SYNC,
);
OTHER_CPLUSPLUSFLAGS = ( OTHER_CPLUSPLUSFLAGS = (
"$(inherited)", "$(inherited)",
"-isystem", "-isystem",
../core/include, "$(SRCROOT)/../vendor/core/include",
"-isystem",
"$(SRCROOT)/../vendor/sync/include",
); );
OTHER_LIBTOOLFLAGS = "$(SRCROOT)/../core/librealm-ios.a"; OTHER_LIBTOOLFLAGS = "$(SRCROOT)/../vendor/core/librealm-ios.a $(SRCROOT)/../vendor/sync/librealm-ios.a";
PRODUCT_NAME = RealmJS; PRODUCT_NAME = RealmJS;
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
}; };
@ -1212,15 +1123,6 @@
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release; defaultConfigurationName = Release;
}; };
F62BF8FF1CAC71780022BCDC /* Build configuration list for PBXNativeTarget "RealmNode" */ = {
isa = XCConfigurationList;
buildConfigurations = (
F62BF8FC1CAC71780022BCDC /* Debug */,
F62BF8FE1CAC71780022BCDC /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
F63FF2C41C1241E500B3B8E0 /* Build configuration list for PBXNativeTarget "RealmJS" */ = { F63FF2C41C1241E500B3B8E0 /* Build configuration list for PBXNativeTarget "RealmJS" */ = {
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0720" LastUpgradeVersion = "0800"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0720" LastUpgradeVersion = "0800"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,26 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0730" LastUpgradeVersion = "0800"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"> buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "F62BF8FA1CAC71780022BCDC"
BuildableName = "libRealmNode.dylib"
BlueprintName = "RealmNode"
ReferencedContainer = "container:RealmJS.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction> </BuildAction>
<TestAction <TestAction
buildConfiguration = "Debug" buildConfiguration = "Debug"
@ -29,24 +13,6 @@
shouldUseLaunchSchemeArgsEnv = "YES"> shouldUseLaunchSchemeArgsEnv = "YES">
<Testables> <Testables>
</Testables> </Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "YES"
customWorkingDirectory = "$(TEMP_DIR)"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<PathRunnable
runnableDebuggingMode = "0"
FilePath = "/usr/local/bin/node">
</PathRunnable>
<MacroExpansion> <MacroExpansion>
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
@ -56,9 +22,27 @@
ReferencedContainer = "container:RealmJS.xcodeproj"> ReferencedContainer = "container:RealmJS.xcodeproj">
</BuildableReference> </BuildableReference>
</MacroExpansion> </MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "YES"
customWorkingDirectory = "~/src/realm/sync/realm-js"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<PathRunnable
runnableDebuggingMode = "0"
FilePath = "/usr/local/bin/node">
</PathRunnable>
<CommandLineArguments> <CommandLineArguments>
<CommandLineArgument <CommandLineArgument
argument = "$(SRCROOT)/../tests" argument = "test.js"
isEnabled = "YES"> isEnabled = "YES">
</CommandLineArgument> </CommandLineArgument>
</CommandLineArguments> </CommandLineArguments>
@ -71,15 +55,6 @@
savedToolIdentifier = "" savedToolIdentifier = ""
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES"> debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "F62BF8FA1CAC71780022BCDC"
BuildableName = "libRealmNode.dylib"
BlueprintName = "RealmNode"
ReferencedContainer = "container:RealmJS.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction> </ProfileAction>
<AnalyzeAction <AnalyzeAction
buildConfiguration = "Debug"> buildConfiguration = "Debug">

View File

@ -93,7 +93,7 @@ void remove_realm_files_from_directory(const std::string &directory)
NSString *fileDir = @(directory.c_str()); NSString *fileDir = @(directory.c_str());
for (NSString *path in [manager enumeratorAtPath:fileDir]) { for (NSString *path in [manager enumeratorAtPath:fileDir]) {
if (![path containsString:@".realm"]) { if (![path.pathExtension isEqualToString:@"realm"] && ![path.pathExtension isEqualToString:@"realm.lock"] && ![path.pathExtension isEqualToString:@"realm.management"]) {
continue; continue;
} }
if (![manager removeItemAtPath:[fileDir stringByAppendingPathComponent:path] error:nil]) { if (![manager removeItemAtPath:[fileDir stringByAppendingPathComponent:path] error:nil]) {

View File

@ -19,6 +19,10 @@
#pragma once #pragma once
#include "js_class.hpp" #include "js_class.hpp"
#include "js_types.hpp"
#include "js_observable.hpp"
#include "collection_notifications.hpp"
namespace realm { namespace realm {
namespace js { namespace js {
@ -27,9 +31,40 @@ namespace js {
class Collection {}; class Collection {};
template<typename T> template<typename T>
struct CollectionClass : ClassDefinition<T, Collection> { struct CollectionClass : ClassDefinition<T, Collection, ObservableClass<T>> {
using ContextType = typename T::Context;
using ValueType = typename T::Value;
using ObjectType = typename T::Object;
using Object = js::Object<T>;
using Value = js::Value<T>;
std::string const name = "Collection"; std::string const name = "Collection";
static inline ValueType create_collection_change_set(ContextType ctx, const CollectionChangeSet &change_set);
}; };
template<typename T>
typename T::Value CollectionClass<T>::create_collection_change_set(ContextType ctx, const CollectionChangeSet &change_set)
{
ObjectType object = Object::create_empty(ctx);
std::vector<ValueType> deletions, insertions, modifications;
for (auto index : change_set.deletions.as_indexes()) {
deletions.push_back(Value::from_number(ctx, index));
}
Object::set_property(ctx, object, "deletions", Object::create_array(ctx, deletions));
for (auto index : change_set.insertions.as_indexes()) {
insertions.push_back(Value::from_number(ctx, index));
}
Object::set_property(ctx, object, "insertions", Object::create_array(ctx, insertions));
for (auto index : change_set.modifications.as_indexes()) {
modifications.push_back(Value::from_number(ctx, index));
}
Object::set_property(ctx, object, "modifications", Object::create_array(ctx, modifications));
return object;
}
} // js } // js
} // realm } // realm

View File

@ -33,10 +33,20 @@ namespace realm {
namespace js { namespace js {
template<typename T> template<typename T>
struct ListClass : ClassDefinition<T, realm::List, CollectionClass<T>> { class List : public realm::List {
public:
List(std::shared_ptr<Realm> r, const ObjectSchema& s, LinkViewRef l) noexcept : realm::List(r, l) {}
List(const realm::List &l) : realm::List(l) {}
std::vector<std::pair<Protected<typename T::Function>, NotificationToken>> m_notification_tokens;
};
template<typename T>
struct ListClass : ClassDefinition<T, realm::js::List<T>, CollectionClass<T>> {
using ContextType = typename T::Context; using ContextType = typename T::Context;
using ObjectType = typename T::Object; using ObjectType = typename T::Object;
using ValueType = typename T::Value; using ValueType = typename T::Value;
using FunctionType = typename T::Function;
using Object = js::Object<T>; using Object = js::Object<T>;
using Value = js::Value<T>; using Value = js::Value<T>;
using ReturnValue = js::ReturnValue<T>; using ReturnValue = js::ReturnValue<T>;
@ -59,6 +69,11 @@ struct ListClass : ClassDefinition<T, realm::List, CollectionClass<T>> {
static void sorted(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &); static void sorted(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &);
static void is_valid(ContextType, ObjectType, size_t, const ValueType [], ReturnValue &); static void is_valid(ContextType, ObjectType, size_t, const ValueType [], ReturnValue &);
// observable
static void add_listener(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &);
static void remove_listener(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &);
static void remove_all_listeners(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &);
std::string const name = "List"; std::string const name = "List";
MethodMap<T> const methods = { MethodMap<T> const methods = {
@ -71,6 +86,9 @@ struct ListClass : ClassDefinition<T, realm::List, CollectionClass<T>> {
{"filtered", wrap<filtered>}, {"filtered", wrap<filtered>},
{"sorted", wrap<sorted>}, {"sorted", wrap<sorted>},
{"isValid", wrap<is_valid>}, {"isValid", wrap<is_valid>},
{"addListener", wrap<add_listener>},
{"removeListener", wrap<remove_listener>},
{"removeAllListeners", wrap<remove_all_listeners>},
}; };
PropertyMap<T> const properties = { PropertyMap<T> const properties = {
@ -82,7 +100,7 @@ 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(std::move(list))); return create_object<T, ListClass<T>>(ctx, new realm::js::List<T>(std::move(list)));
} }
template<typename T> template<typename T>
@ -231,5 +249,54 @@ void ListClass<T>::is_valid(ContextType ctx, ObjectType this_object, size_t argc
return_value.set(get_internal<T, ListClass<T>>(this_object)->is_valid()); return_value.set(get_internal<T, ListClass<T>>(this_object)->is_valid());
} }
template<typename T>
void ListClass<T>::add_listener(ContextType ctx, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
validate_argument_count(argc, 1);
auto list = get_internal<T, ListClass<T>>(this_object);
auto callback = Value::validated_to_function(ctx, arguments[0]);
Protected<FunctionType> protected_callback(ctx, callback);
Protected<ObjectType> protected_this(ctx, this_object);
Protected<typename T::GlobalContext> protected_ctx(Context<T>::get_global_context(ctx));
auto token = list->add_notification_callback([=](CollectionChangeSet change_set, std::exception_ptr exception) {
HANDLESCOPE
ValueType arguments[2];
arguments[0] = static_cast<ObjectType>(protected_this);
arguments[1] = CollectionClass<T>::create_collection_change_set(protected_ctx, change_set);
Function<T>::call(protected_ctx, protected_callback, protected_this, 2, arguments);
});
list->m_notification_tokens.emplace_back(protected_callback, std::move(token));
}
template<typename T>
void ListClass<T>::remove_listener(ContextType ctx, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
validate_argument_count(argc, 1);
auto list = get_internal<T, ListClass<T>>(this_object);
auto callback = Value::validated_to_function(ctx, arguments[0]);
auto protected_function = Protected<FunctionType>(ctx, callback);
auto iter = list->m_notification_tokens.begin();
typename Protected<FunctionType>::Comparator compare;
while (iter != list->m_notification_tokens.end()) {
if(compare(iter->first, protected_function)) {
iter = list->m_notification_tokens.erase(iter);
}
else {
iter++;
}
}
}
template<typename T>
void ListClass<T>::remove_all_listeners(ContextType ctx, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
validate_argument_count(argc, 0);
auto list = get_internal<T, ListClass<T>>(this_object);
list->m_notification_tokens.clear();
}
} // js } // js
} // realm } // realm

35
src/js_observable.hpp Normal file
View File

@ -0,0 +1,35 @@
////////////////////////////////////////////////////////////////////////////
//
// 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.
//
////////////////////////////////////////////////////////////////////////////
#pragma once
#include "js_class.hpp"
namespace realm {
namespace js {
// Empty class that merely serves as useful type for now.
class Observable {};
template<typename T>
struct ObservableClass : ClassDefinition<T, Observable> {
std::string const name = "Observable";
};
} // js
} // realm

View File

@ -28,6 +28,13 @@
#include "js_list.hpp" #include "js_list.hpp"
#include "js_results.hpp" #include "js_results.hpp"
#include "js_schema.hpp" #include "js_schema.hpp"
#include "js_observable.hpp"
#if REALM_ENABLE_SYNC
#include "js_sync.hpp"
#include "sync/sync_config.hpp"
#include "sync/sync_manager.hpp"
#endif
#include "shared_realm.hpp" #include "shared_realm.hpp"
#include "binding_context.hpp" #include "binding_context.hpp"
@ -101,6 +108,8 @@ class RealmDelegate : public BindingContext {
std::weak_ptr<realm::Realm> m_realm; std::weak_ptr<realm::Realm> m_realm;
void notify(const char *notification_name) { void notify(const char *notification_name) {
HANDLESCOPE
SharedRealm realm = m_realm.lock(); SharedRealm realm = m_realm.lock();
if (!realm) { if (!realm) {
throw std::runtime_error("Realm no longer exists"); throw std::runtime_error("Realm no longer exists");
@ -111,7 +120,8 @@ class RealmDelegate : public BindingContext {
arguments[0] = realm_object; arguments[0] = realm_object;
arguments[1] = Value::from_string(m_context, notification_name); arguments[1] = Value::from_string(m_context, notification_name);
for (auto &callback : m_notifications) { std::list<Protected<FunctionType>> notifications_copy(m_notifications);
for (auto &callback : notifications_copy) {
Function<T>::call(m_context, callback, realm_object, 2, arguments); Function<T>::call(m_context, callback, realm_object, 2, arguments);
} }
} }
@ -124,7 +134,7 @@ void set_default_path(std::string path);
void delete_all_realms(); void delete_all_realms();
template<typename T> template<typename T>
class RealmClass : public ClassDefinition<T, SharedRealm> { class RealmClass : public ClassDefinition<T, SharedRealm, ObservableClass<T>> {
using GlobalContextType = typename T::GlobalContext; using GlobalContextType = typename T::GlobalContext;
using ContextType = typename T::Context; using ContextType = typename T::Context;
using FunctionType = typename T::Function; using FunctionType = typename T::Function;
@ -261,6 +271,12 @@ inline typename T::Function RealmClass<T>::create_constructor(ContextType ctx) {
Object::set_property(ctx, realm_constructor, "Results", results_constructor, attributes); Object::set_property(ctx, realm_constructor, "Results", results_constructor, attributes);
Object::set_property(ctx, realm_constructor, "Object", realm_object_constructor, attributes); Object::set_property(ctx, realm_constructor, "Object", realm_object_constructor, attributes);
#if REALM_ENABLE_SYNC
FunctionType sync_constructor = SyncClass<T>::create_constructor(ctx);
Object::set_property(ctx, realm_constructor, "Sync", sync_constructor, attributes);
#endif
Object::set_global(ctx, "Realm", realm_constructor);
return realm_constructor; return realm_constructor;
} }
@ -338,7 +354,7 @@ void RealmClass<T>::constructor(ContextType ctx, ObjectType this_object, size_t
if (!Value::is_undefined(ctx, version_value)) { if (!Value::is_undefined(ctx, version_value)) {
config.schema_version = Value::validated_to_number(ctx, version_value, "schemaVersion"); config.schema_version = Value::validated_to_number(ctx, version_value, "schemaVersion");
} }
else { else if (schema_updated) {
config.schema_version = 0; config.schema_version = 0;
} }
@ -376,6 +392,9 @@ void RealmClass<T>::constructor(ContextType ctx, ObjectType this_object, size_t
std::string encryption_key = NativeAccessor::to_binary(ctx, encryption_key_value); std::string encryption_key = NativeAccessor::to_binary(ctx, encryption_key_value);
config.encryption_key = std::vector<char>(encryption_key.begin(), encryption_key.end()); config.encryption_key = std::vector<char>(encryption_key.begin(), encryption_key.end());
} }
#if REALM_ENABLE_SYNC
SyncClass<T>::populate_sync_config(ctx, Value::validated_to_object(ctx, Object::get_global(ctx, "Realm")), object, config);
#endif
} }
} }
else { else {
@ -431,9 +450,17 @@ void RealmClass<T>::schema_version(ContextType ctx, ObjectType this_object, size
} }
} }
template<typename T> template<typename T>
void RealmClass<T>::clear_test_state(ContextType ctx, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) { void RealmClass<T>::clear_test_state(ContextType ctx, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
validate_argument_count(argc, 0); validate_argument_count(argc, 0);
#if REALM_ENABLE_SYNC
for(auto &user : SyncManager::shared().all_users()) {
user->log_out();
}
SyncManager::shared().reset_for_testing();
SyncManager::shared().configure_file_system(default_realm_file_directory(), SyncManager::MetadataMode::NoEncryption);
#endif
delete_all_realms(); delete_all_realms();
} }

View File

@ -31,10 +31,25 @@ namespace realm {
namespace js { namespace js {
template<typename T> template<typename T>
struct ResultsClass : ClassDefinition<T, realm::Results, CollectionClass<T>> { class Results : public realm::Results {
public:
Results(Results const& r) : realm::Results(r) {};
Results(realm::Results const& r) : realm::Results(r) {};
Results(Results&&) = default;
Results& operator=(Results&&) = default;
Results& operator=(Results const&) = default;
using realm::Results::Results;
std::vector<std::pair<Protected<typename T::Function>, NotificationToken>> m_notification_tokens;
};
template<typename T>
struct ResultsClass : ClassDefinition<T, realm::js::Results<T>, CollectionClass<T>> {
using ContextType = typename T::Context; using ContextType = typename T::Context;
using ObjectType = typename T::Object; using ObjectType = typename T::Object;
using ValueType = typename T::Value; using ValueType = typename T::Value;
using FunctionType = typename T::Function;
using Object = js::Object<T>; using Object = js::Object<T>;
using Value = js::Value<T>; using Value = js::Value<T>;
using ReturnValue = js::ReturnValue<T>; using ReturnValue = js::ReturnValue<T>;
@ -56,6 +71,11 @@ struct ResultsClass : ClassDefinition<T, realm::Results, CollectionClass<T>> {
static void sorted(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &); static void sorted(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &);
static void is_valid(ContextType, ObjectType, size_t, const ValueType [], ReturnValue &); static void is_valid(ContextType, ObjectType, size_t, const ValueType [], ReturnValue &);
// observable
static void add_listener(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &);
static void remove_listener(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &);
static void remove_all_listeners(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &);
std::string const name = "Results"; std::string const name = "Results";
MethodMap<T> const methods = { MethodMap<T> const methods = {
@ -63,6 +83,9 @@ struct ResultsClass : ClassDefinition<T, realm::Results, CollectionClass<T>> {
{"filtered", wrap<filtered>}, {"filtered", wrap<filtered>},
{"sorted", wrap<sorted>}, {"sorted", wrap<sorted>},
{"isValid", wrap<is_valid>}, {"isValid", wrap<is_valid>},
{"addListener", wrap<add_listener>},
{"removeListener", wrap<remove_listener>},
{"removeAllListeners", wrap<remove_all_listeners>},
}; };
PropertyMap<T> const properties = { PropertyMap<T> const properties = {
@ -74,13 +97,13 @@ struct ResultsClass : ClassDefinition<T, realm::Results, CollectionClass<T>> {
template<typename T> template<typename T>
typename T::Object ResultsClass<T>::create_instance(ContextType ctx, realm::Results results) { typename T::Object ResultsClass<T>::create_instance(ContextType ctx, realm::Results results) {
return create_object<T, ResultsClass<T>>(ctx, new realm::Results(std::move(results))); return create_object<T, ResultsClass<T>>(ctx, new realm::js::Results<T>(std::move(results)));
} }
template<typename T> template<typename T>
typename T::Object ResultsClass<T>::create_instance(ContextType ctx, SharedRealm realm, const ObjectSchema &object_schema) { typename T::Object ResultsClass<T>::create_instance(ContextType ctx, SharedRealm realm, const ObjectSchema &object_schema) {
auto table = ObjectStore::table_for_object_type(realm->read_group(), object_schema.name); auto table = ObjectStore::table_for_object_type(realm->read_group(), object_schema.name);
return create_object<T, ResultsClass<T>>(ctx, new realm::Results(realm, *table)); return create_object<T, ResultsClass<T>>(ctx, new realm::js::Results<T>(realm, *table));
} }
template<typename T> template<typename T>
@ -155,7 +178,7 @@ typename T::Object ResultsClass<T>::create_sorted(ContextType ctx, const U &coll
} }
auto table = realm::ObjectStore::table_for_object_type(realm->read_group(), object_schema.name); auto table = realm::ObjectStore::table_for_object_type(realm->read_group(), object_schema.name);
auto results = new realm::Results(realm, collection.get_query(), auto results = new realm::js::Results<T>(realm, collection.get_query(),
{*table, std::move(columns), std::move(ascending)}); {*table, std::move(columns), std::move(ascending)});
return create_object<T, ResultsClass<T>>(ctx, results); return create_object<T, ResultsClass<T>>(ctx, results);
} }
@ -210,5 +233,54 @@ void ResultsClass<T>::is_valid(ContextType ctx, ObjectType this_object, size_t a
return_value.set(get_internal<T, ResultsClass<T>>(this_object)->is_valid()); return_value.set(get_internal<T, ResultsClass<T>>(this_object)->is_valid());
} }
template<typename T>
void ResultsClass<T>::add_listener(ContextType ctx, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
validate_argument_count(argc, 1);
auto results = get_internal<T, ResultsClass<T>>(this_object);
auto callback = Value::validated_to_function(ctx, arguments[0]);
Protected<FunctionType> protected_callback(ctx, callback);
Protected<ObjectType> protected_this(ctx, this_object);
Protected<typename T::GlobalContext> protected_ctx(Context<T>::get_global_context(ctx));
auto token = results->add_notification_callback([=](CollectionChangeSet change_set, std::exception_ptr exception) {
HANDLESCOPE
ValueType arguments[2];
arguments[0] = static_cast<ObjectType>(protected_this);
arguments[1] = CollectionClass<T>::create_collection_change_set(protected_ctx, change_set);
Function<T>::call(protected_ctx, protected_callback, protected_this, 2, arguments);
});
results->m_notification_tokens.emplace_back(protected_callback, std::move(token));
}
template<typename T>
void ResultsClass<T>::remove_listener(ContextType ctx, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
validate_argument_count(argc, 1);
auto results = get_internal<T, ResultsClass<T>>(this_object);
auto callback = Value::validated_to_function(ctx, arguments[0]);
auto protected_function = Protected<FunctionType>(ctx, callback);
auto iter = results->m_notification_tokens.begin();
typename Protected<FunctionType>::Comparator compare;
while (iter != results->m_notification_tokens.end()) {
if(compare(iter->first, protected_function)) {
iter = results->m_notification_tokens.erase(iter);
}
else {
iter++;
}
}
}
template<typename T>
void ResultsClass<T>::remove_all_listeners(ContextType ctx, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
validate_argument_count(argc, 0);
auto results = get_internal<T, ResultsClass<T>>(this_object);
results->m_notification_tokens.clear();
}
} // js } // js
} // realm } // realm

314
src/js_sync.hpp Normal file
View File

@ -0,0 +1,314 @@
////////////////////////////////////////////////////////////////////////////
//
// 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.
//
////////////////////////////////////////////////////////////////////////////
#pragma once
#include <list>
#include <map>
#include <set>
#include "platform.hpp"
#include "js_class.hpp"
#include "js_collection.hpp"
#include "sync/sync_manager.hpp"
#include "sync/sync_config.hpp"
#include "sync/sync_session.hpp"
#include "sync/sync_user.hpp"
#include "realm/util/logger.hpp"
#include "realm/util/uri.hpp"
namespace realm {
namespace js {
using SharedUser = std::shared_ptr<realm::SyncUser>;
template<typename T>
class UserClass : public ClassDefinition<T, SharedUser> {
using GlobalContextType = typename T::GlobalContext;
using ContextType = typename T::Context;
using FunctionType = typename T::Function;
using ObjectType = typename T::Object;
using ValueType = typename T::Value;
using String = js::String<T>;
using Object = js::Object<T>;
using Value = js::Value<T>;
using Function = js::Function<T>;
using ReturnValue = js::ReturnValue<T>;
using NativeAccessor = realm::NativeAccessor<ValueType, ContextType>;
public:
std::string const name = "User";
static FunctionType create_constructor(ContextType);
static void get_server(ContextType, ObjectType, ReturnValue &);
static void get_identity(ContextType, ObjectType, ReturnValue &);
static void get_token(ContextType, ObjectType, ReturnValue &);
static void is_admin(ContextType, ObjectType, ReturnValue &);
PropertyMap<T> const properties = {
{"server", {wrap<get_server>, nullptr}},
{"identity", {wrap<get_identity>, nullptr}},
{"token", {wrap<get_token>, nullptr}},
{"isAdmin", {wrap<is_admin>, nullptr}},
};
static void create_user(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &);
MethodMap<T> const static_methods = {
{"createUser", wrap<create_user>}
};
static void current_user(ContextType ctx, ObjectType object, ReturnValue &return_value);
static void all_users(ContextType ctx, ObjectType object, ReturnValue &return_value);
PropertyMap<T> const static_properties = {
{"current", {wrap<current_user>, nullptr}},
{"all", {wrap<all_users>, nullptr}},
};
static void logout(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &);
MethodMap<T> const methods = {
{"logout", wrap<logout>}
};
};
template<typename T>
void UserClass<T>::get_server(ContextType ctx, ObjectType object, ReturnValue &return_value) {
std::string server = get_internal<T, UserClass<T>>(object)->get()->server_url();
return_value.set(server);
}
template<typename T>
void UserClass<T>::get_identity(ContextType ctx, ObjectType object, ReturnValue &return_value) {
std::string identity = get_internal<T, UserClass<T>>(object)->get()->identity();
return_value.set(identity);
}
template<typename T>
void UserClass<T>::get_token(ContextType ctx, ObjectType object, ReturnValue &return_value) {
std::string token = get_internal<T, UserClass<T>>(object)->get()->refresh_token();
return_value.set(token);
}
template<typename T>
void UserClass<T>::is_admin(ContextType ctx, ObjectType object, ReturnValue &return_value) {
return_value.set(get_internal<T, UserClass<T>>(object)->get()->is_admin());
}
template<typename T>
void UserClass<T>::create_user(ContextType ctx, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
validate_argument_count(argc, 3, 4);
SharedUser *user = new SharedUser(SyncManager::shared().get_user(
Value::validated_to_string(ctx, arguments[1]),
Value::validated_to_string(ctx, arguments[2]),
(std::string)Value::validated_to_string(ctx, arguments[0]),
Value::validated_to_boolean(ctx, arguments[3])));
return_value.set(create_object<T, UserClass<T>>(ctx, user));
}
template<typename T>
void UserClass<T>::all_users(ContextType ctx, ObjectType object, ReturnValue &return_value) {
auto users = Object::create_empty(ctx);
for (auto user : SyncManager::shared().all_users()) {
if (user->state() == SyncUser::State::Active) {
Object::set_property(ctx, users, user->identity(), create_object<T, UserClass<T>>(ctx, new SharedUser(user)), ReadOnly | DontDelete);
}
}
return_value.set(users);
}
template<typename T>
void UserClass<T>::current_user(ContextType ctx, ObjectType object, ReturnValue &return_value) {
SharedUser *current = nullptr;
for (auto user : SyncManager::shared().all_users()) {
if (user->state() == SyncUser::State::Active) {
if (current != nullptr) {
throw std::runtime_error("More than one user logged in currently.");
}
current = new SharedUser(user);
}
}
if (current != nullptr) {
return_value.set(create_object<T, UserClass<T>>(ctx, current));
}
else {
return_value.set_undefined();
}
}
template<typename T>
void UserClass<T>::logout(ContextType ctx, ObjectType object, size_t, const ValueType[], ReturnValue &) {
get_internal<T, UserClass<T>>(object)->get()->log_out();
}
template<typename T>
class SyncClass : public ClassDefinition<T, void *> {
using GlobalContextType = typename T::GlobalContext;
using ContextType = typename T::Context;
using FunctionType = typename T::Function;
using ObjectType = typename T::Object;
using ValueType = typename T::Value;
using String = js::String<T>;
using Object = js::Object<T>;
using Value = js::Value<T>;
using Function = js::Function<T>;
using ReturnValue = js::ReturnValue<T>;
using NativeAccessor = realm::NativeAccessor<ValueType, ContextType>;
public:
std::string const name = "Sync";
static FunctionType create_constructor(ContextType);
static void set_sync_log_level(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &);
static void set_verify_servers_ssl_certificate(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &);
// private
static void refresh_access_token(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &);
static void populate_sync_config(ContextType, ObjectType realm_constructor, ObjectType config_object, Realm::Config&);
// static properties
static void get_is_developer_edition(ContextType, ObjectType, ReturnValue &);
MethodMap<T> const static_methods = {
{"refreshAccessToken", wrap<refresh_access_token>},
{"setLogLevel", wrap<set_sync_log_level>},
{"setVerifyServersSslCertificate", wrap<set_verify_servers_ssl_certificate>}
};
};
template<typename T>
inline typename T::Function SyncClass<T>::create_constructor(ContextType ctx) {
// setup synced realmFile paths
ensure_directory_exists_for_file(default_realm_file_directory());
SyncManager::shared().configure_file_system(default_realm_file_directory(), SyncManager::MetadataMode::NoEncryption);
FunctionType sync_constructor = ObjectWrap<T, SyncClass<T>>::create_constructor(ctx);
PropertyAttributes attributes = ReadOnly | DontEnum | DontDelete;
Object::set_property(ctx, sync_constructor, "User", ObjectWrap<T, UserClass<T>>::create_constructor(ctx), attributes);
realm::SyncManager::shared().set_error_handler([=](int error_code, std::string message) {
std::cout << error_code << " " << message << std::endl;
});
return sync_constructor;
}
template<typename T>
void SyncClass<T>::set_sync_log_level(ContextType ctx, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
validate_argument_count(argc, 1);
std::string log_level = Value::validated_to_string(ctx, arguments[0]);
std::istringstream in(log_level); // Throws
in.imbue(std::locale::classic()); // Throws
in.unsetf(std::ios_base::skipws);
util::Logger::Level log_level_2 = util::Logger::Level();
in >> log_level_2; // Throws
if (!in || !in.eof())
throw std::runtime_error("Bad log level");
realm::SyncManager::shared().set_log_level(log_level_2);
}
template<typename T>
void SyncClass<T>::set_verify_servers_ssl_certificate(ContextType ctx, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
validate_argument_count(argc, 1);
bool verify_servers_ssl_certificate = Value::validated_to_boolean(ctx, arguments[0]);
realm::SyncManager::shared().set_client_should_validate_ssl(verify_servers_ssl_certificate);
}
template<typename T>
void SyncClass<T>::refresh_access_token(ContextType ctx, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
validate_argument_count(argc, 2);
static const String token_string = "token";
static const String file_url_string = "file_url";
static const String realm_url_string = "resolved_realm_url";
ObjectType json_arguments = Value::validated_to_object(ctx, arguments[1]);
std::string token = Object::validated_get_string(ctx, json_arguments, token_string);
std::string file_url = Object::validated_get_string(ctx, json_arguments, file_url_string);
std::string realm_url = Object::validated_get_string(ctx, json_arguments, realm_url_string);
if (auto session = SyncManager::shared().get_existing_active_session(file_url)) {
session->refresh_access_token(token, realm_url);
return_value.set(true);
}
else {
return_value.set(false);
}
}
template<typename T>
void SyncClass<T>::populate_sync_config(ContextType ctx, ObjectType realm_constructor, ObjectType config_object, Realm::Config& config) {
ValueType sync_config_value = Object::get_property(ctx, config_object, "sync");
if (!Value::is_undefined(ctx, sync_config_value)) {
auto sync_config_object = Value::validated_to_object(ctx, sync_config_value);
ObjectType sync_constructor = Object::validated_get_object(ctx, realm_constructor, std::string("Sync"));
Protected<ValueType> refresh(ctx, Object::validated_get_function(ctx, sync_constructor, std::string("refreshAccessToken")));
Protected<ObjectType> protected_sync(ctx, sync_constructor);
Protected<typename T::GlobalContext> protected_ctx(Context<T>::get_global_context(ctx));
auto handler = [=](const std::string& path, const realm::SyncConfig& config, std::shared_ptr<SyncSession>) {
HANDLESCOPE
if (config.user->is_admin()) {
// FIXME: This log-in callback is called while the object store still holds some sync-related locks.
// Notify the object store of the access token asynchronously to avoid the deadlock that would result
// from reentering the object store here.
auto thread = std::thread([path, config]{
auto session = SyncManager::shared().get_existing_active_session(path);
session->refresh_access_token(config.user->refresh_token(), config.realm_url);
});
thread.detach();
}
else {
ObjectType user_constructor = Object::validated_get_object(ctx, protected_sync, std::string("User"));
FunctionType authenticate = Object::validated_get_function(ctx, user_constructor, std::string("_authenticateRealm"));
ValueType arguments[3];
arguments[0] = Value::from_string(protected_ctx, path.c_str());
arguments[1] = Value::from_string(protected_ctx, config.realm_url.c_str());
arguments[2] = refresh;
ObjectType user = create_object<T, UserClass<T>>(ctx, new SharedUser(config.user));
Function::call(protected_ctx, authenticate, user, 3, arguments);
}
};
ObjectType user = Object::validated_get_object(ctx, sync_config_object, "user");
SharedUser shared_user = *get_internal<T, UserClass<T>>(user);
if (shared_user->state() != SyncUser::State::Active) {
throw std::runtime_error("User is no longer valid.");
}
std::string raw_realm_url = Object::validated_get_string(ctx, sync_config_object, "url");
// FIXME - use make_shared
config.sync_config = std::shared_ptr<SyncConfig>(
new SyncConfig(shared_user, raw_realm_url, SyncSessionStopPolicy::AfterChangesUploaded, handler)
);
config.schema_mode = SchemaMode::Additive;
config.path = realm::SyncManager::shared().path_for_realm(shared_user->identity(), raw_realm_url);
}
}
} // js
} // realm

View File

@ -133,6 +133,11 @@ struct Function {
using ValueType = typename T::Value; using ValueType = typename T::Value;
static ValueType call(ContextType, const FunctionType &, const ObjectType &, size_t, const ValueType[]); static ValueType call(ContextType, const FunctionType &, const ObjectType &, size_t, const ValueType[]);
template<size_t N> static ValueType call(ContextType ctx, const FunctionType &function,
const ObjectType &this_object, const ValueType (&arguments)[N])
{
return call(ctx, function, this_object, N, arguments);
}
static ValueType call(ContextType ctx, const FunctionType &function, size_t argument_count, const ValueType arguments[]) { static ValueType call(ContextType ctx, const FunctionType &function, size_t argument_count, const ValueType arguments[]) {
return call(ctx, function, {}, argument_count, arguments); return call(ctx, function, {}, argument_count, arguments);
} }
@ -165,6 +170,9 @@ struct Object {
static void set_property(ContextType, const ObjectType &, uint32_t, const ValueType &); static void set_property(ContextType, const ObjectType &, uint32_t, const ValueType &);
static std::vector<String<T>> get_property_names(ContextType, const ObjectType &); static std::vector<String<T>> get_property_names(ContextType, const ObjectType &);
static void set_global(ContextType, const String<T> &, const ValueType &);
static ValueType get_global(ContextType, const String<T> &);
template<typename P> template<typename P>
static ValueType validated_get_property(ContextType ctx, const ObjectType &object, const P &property, const char *message = nullptr) { static ValueType validated_get_property(ContextType ctx, const ObjectType &object, const P &property, const char *message = nullptr) {
if (!has_property(ctx, object, property)) { if (!has_property(ctx, object, property)) {
@ -247,6 +255,10 @@ class Protected {
bool operator!=(const ValueType &) const; bool operator!=(const ValueType &) const;
bool operator==(const Protected<ValueType> &) const; bool operator==(const Protected<ValueType> &) const;
bool operator!=(const Protected<ValueType> &) const; bool operator!=(const Protected<ValueType> &) const;
struct Comparator {
bool operator()(const Protected<ValueType>& a, const Protected<ValueType>& b) const;
};
}; };
template<typename T> template<typename T>

View File

@ -26,7 +26,6 @@ extern "C" {
JSObjectRef RJSConstructorCreate(JSContextRef ctx); JSObjectRef RJSConstructorCreate(JSContextRef ctx);
void RJSInitializeInContext(JSContextRef ctx); void RJSInitializeInContext(JSContextRef ctx);
void RJSClearTestState(void);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -143,5 +143,17 @@ inline void jsc::Object::set_internal(const JSObjectRef &object, typename ClassT
*wrap = ptr; *wrap = ptr;
} }
template<>
inline void jsc::Object::set_global(JSContextRef ctx, const jsc::String &key, const JSValueRef &value) {
JSObjectRef global_object = JSContextGetGlobalObject(ctx);
jsc::Object::set_property(ctx, global_object, key, value, js::ReadOnly | js::DontEnum | js::DontDelete);
}
template<>
inline JSValueRef jsc::Object::get_global(JSContextRef ctx, const jsc::String &key) {
JSObjectRef global_object = JSContextGetGlobalObject(ctx);
return jsc::Object::get_property(ctx, global_object, key);
}
} // js } // js
} // realm } // realm

View File

@ -47,10 +47,17 @@ class Protected<JSGlobalContextRef> {
operator bool() const { operator bool() const {
return m_context != nullptr; return m_context != nullptr;
} }
struct Comparator {
bool operator() (const Protected<JSGlobalContextRef>& a, const Protected<JSGlobalContextRef>& b) const {
return a.m_context == b.m_context;
}
};
}; };
template<> template<>
class Protected<JSValueRef> { class Protected<JSValueRef> {
protected:
JSGlobalContextRef m_context; JSGlobalContextRef m_context;
JSValueRef m_value; JSValueRef m_value;
@ -75,6 +82,21 @@ class Protected<JSValueRef> {
operator bool() const { operator bool() const {
return m_value != nullptr; return m_value != nullptr;
} }
struct Comparator {
bool operator() (const Protected<JSValueRef>& a, const Protected<JSValueRef>& b) const {
if (a.m_context != b.m_context) {
return false;
}
return JSValueIsStrictEqual(a.m_context, a.m_value, b.m_value);
}
};
Protected<JSValueRef>& operator=(Protected<JSValueRef> other) {
std::swap(m_context, other.m_context);
std::swap(m_value, other.m_value);
return *this;
}
}; };
template<> template<>
@ -89,6 +111,12 @@ class Protected<JSObjectRef> : public Protected<JSValueRef> {
JSValueRef value = static_cast<JSValueRef>(*this); JSValueRef value = static_cast<JSValueRef>(*this);
return (JSObjectRef)value; return (JSObjectRef)value;
} }
Protected<JSObjectRef>& operator=(Protected<JSObjectRef> other) {
std::swap(m_context, other.m_context);
std::swap(m_value, other.m_value);
return *this;
}
}; };
} // js } // js

View File

@ -24,6 +24,8 @@
#include "js_types.hpp" #include "js_types.hpp"
#define HANDLESCOPE
namespace realm { namespace realm {
namespace jsc { namespace jsc {

View File

@ -1,85 +0,0 @@
{
"targets": [
{
"target_name": "realm",
"sources": [
"node_init.cpp",
"platform.cpp",
"../js_realm.cpp",
"../object-store/src/collection_notifications.cpp",
"../object-store/src/index_set.cpp",
"../object-store/src/list.cpp",
"../object-store/src/object_schema.cpp",
"../object-store/src/object_store.cpp",
"../object-store/src/results.cpp",
"../object-store/src/schema.cpp",
"../object-store/src/shared_realm.cpp",
"../object-store/src/thread_confined.cpp",
"../object-store/src/impl/collection_change_builder.cpp",
"../object-store/src/impl/collection_notifier.cpp",
"../object-store/src/impl/handover.cpp",
"../object-store/src/impl/list_notifier.cpp",
"../object-store/src/impl/realm_coordinator.cpp",
"../object-store/src/impl/results_notifier.cpp",
"../object-store/src/impl/transact_log_handler.cpp",
"../object-store/src/impl/node/weak_realm_notifier.cpp",
"../object-store/src/parser/parser.cpp",
"../object-store/src/parser/query_builder.cpp",
"../object-store/src/util/format.cpp",
"../object-store/src/util/thread_id.cpp"
],
"include_dirs": [
"..",
"../object-store/src",
"../object-store/src/impl",
"../object-store/src/impl/apple",
"../object-store/src/parser",
"../object-store/external/pegtl",
"../../core-node/include",
"<!(node -e 'require(\"nan\")')"
],
"library_dirs": [
"$(srcdir)/../../core-node"
],
"defines": [
"REALM_HAVE_CONFIG",
"REALM_PLATFORM_NODE=1"
],
"cflags_cc": [
"-fexceptions",
"-frtti",
"-std=c++14",
"-Wno-missing-field-initializers",
"-Wno-return-type"
],
"libraries": ["-lrealm-node"],
"xcode_settings": {
"CLANG_CXX_LANGUAGE_STANDARD": "c++14",
"CLANG_CXX_LIBRARY": "libc++",
"GCC_ENABLE_CPP_EXCEPTIONS": "YES",
"GCC_ENABLE_CPP_RTTI": "YES",
"MACOSX_DEPLOYMENT_TARGET": "10.8",
"OTHER_LDFLAGS": ["-framework", "Foundation"]
},
"conditions": [
[
"OS=='linux'", {
"sources": [
"../object-store/src/impl/android/external_commit_helper.cpp",
]
}
],
["OS=='mac'", {
"sources": [
"../object-store/src/impl/apple/external_commit_helper.cpp"
]
}]
],
"configurations": {
"Debug": {
"defines": ["DEBUG=1"]
}
}
}
]
}

View File

@ -1,28 +0,0 @@
#!/bin/bash
set -o pipefail
set -e
cd "$(dirname "$0")"
CONFIGURATION="${1:-"Release"}"
PATH="$(cd ../../node_modules/.bin && pwd):$PATH"
if [ -s "${HOME}/.nvm/nvm.sh" ]; then
. "${HOME}/.nvm/nvm.sh"
nvm use 5.4.0 || true
fi
node-gyp configure
# Being explicit about debug mode rather than relying on defaults.
if [[ $CONFIGURATION == 'Debug' ]]; then
node-gyp build --debug
else
node-gyp build --no-debug
fi
# Link to the appropriate module in the build directory.
cd ../..
mkdir -p build
ln -fs "../src/node/build/$CONFIGURATION/realm.node" build/

111
src/node/gyp/realm.gyp Normal file
View File

@ -0,0 +1,111 @@
{
"variables": {
"use_realm_debug": "<!(echo $REALMJS_USE_DEBUG_CORE)"
},
"conditions": [
["OS=='mac'", {
"variables": {
"realm_enable_sync%": "0"
}
}, {
"variables": {
"realm_enable_sync%": "0"
}
}]
],
"targets": [
{
"target_name": "realm-core",
"type": "none",
"direct_dependent_settings": {
"conditions": [
["use_realm_debug!=''", {
"libraries": [ "-lrealm-node-dbg" ],
"defines": [ "REALM_DEBUG=1" ]
}, {
"libraries": [ "-lrealm-node" ]
}]
]
},
"all_dependent_settings": {
"defines": [ "REALM_HAVE_CONFIG", "REALM_PLATFORM_NODE=1", "REALM_ENABLE_SYNC=<(realm_enable_sync)" ]
},
"variables": {
"prefix": "<!(echo $REALM_CORE_PREFIX)"
},
"conditions": [
["prefix!=''", {
"all_dependent_settings": {
"include_dirs": [ "<(prefix)/src" ],
},
"direct_dependent_settings": {
"library_dirs": [ "<(prefix)/src/realm" ]
}
}, {
"dependencies": [ "vendored-realm" ]
}]
]
},
{
"target_name": "realm-sync",
"type": "none",
"dependencies": [ "realm-core" ], # sync headers include core headers
"direct_dependent_settings": {
"conditions": [
["use_realm_debug!=''", {
"libraries": [ "-lrealm-sync-node-dbg" ]
}, {
"libraries": [ "-lrealm-sync-node" ]
}]
]
},
"export_dependent_settings": [ "realm-core" ], # depending on sync is tantamount to depending on core
"variables": {
"prefix": "<!(echo $REALM_SYNC_PREFIX)"
},
"conditions": [
["prefix!=''", {
"all_dependent_settings": {
"include_dirs": [ "<(prefix)/src" ],
},
"direct_dependent_settings": {
"library_dirs": [ "<(prefix)/src/realm" ]
}
}, {
"dependencies": [ "vendored-realm" ]
}]
],
},
{
"variables": {
"vendor_dir%": "<(module_root_dir)/vendor",
},
"target_name": "vendored-realm",
"type": "none",
"conditions": [
["realm_enable_sync", {
"all_dependent_settings": {
"include_dirs": [ "<(module_root_dir)/vendor/node-sync/include" ],
"library_dirs": [ "<(module_root_dir)/vendor/node-sync/osx" ]
}
}, {
"all_dependent_settings": {
"include_dirs": [ "<(module_root_dir)/vendor/core-node/include" ],
"library_dirs": [ "<(module_root_dir)/vendor/core-node" ]
},
}],
["realm_download_binaries", {
"actions": [
{
"action_name": "download-realm",
"inputs": [ ],
"outputs": [ "<(module_root_dir)/vendor/core-node" ],
"action": [ "<(module_root_dir)/scripts/download-core.sh", "node", "<(realm_enable_sync)" ]
}
]
}]
]
}
]
}

View File

@ -0,0 +1,40 @@
{
"target_defaults": {
"variables": {
"warning-flags": [
"-Wno-missing-field-initializers",
"-Wno-return-type",
"-Wno-unused-result",
"-Wno-deprecated-declarations",
"-Wundef"
]
},
"cflags_cc!": [ # turn off default flags on older nodes on linux
"-fno-exceptions",
"-fno-rtti",
"-std=gnu++0x"
],
"cflags_cc": [
"-fexceptions",
"-frtti",
"-std=c++14",
"<@(warning-flags)"
],
"include_dirs": [
"<!(node -e \"require('nan')\")"
],
"conditions": [
["OS=='mac'", {
"xcode_settings": {
"CLANG_CXX_LANGUAGE_STANDARD": "c++14",
"CLANG_CXX_LIBRARY": "libc++",
"GCC_ENABLE_CPP_EXCEPTIONS": "YES",
"GCC_ENABLE_CPP_RTTI": "YES",
"MACOSX_DEPLOYMENT_TARGET": "10.8",
"OTHER_LDFLAGS": ["-framework Foundation"],
"WARNING_CFLAGS": [ "<@(warning-flags)" ]
}
}]
]
}
}

View File

@ -49,6 +49,8 @@ class ObjectWrap : public Nan::ObjectWrap {
return Nan::New(js_template); return Nan::New(js_template);
} }
static void construct(const v8::FunctionCallbackInfo<v8::Value>&);
static bool has_instance(v8::Isolate* isolate, const v8::Local<v8::Value> &value) { static bool has_instance(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return get_template()->HasInstance(value); return get_template()->HasInstance(value);
} }
@ -73,27 +75,26 @@ class ObjectWrap : public Nan::ObjectWrap {
static v8::Local<v8::FunctionTemplate> create_template(); static v8::Local<v8::FunctionTemplate> create_template();
static void setup_method(v8::Local<v8::FunctionTemplate>, const std::string &, Nan::FunctionCallback); static void setup_method(v8::Local<v8::FunctionTemplate>, const std::string &, v8::FunctionCallback);
static void setup_static_method(v8::Local<v8::FunctionTemplate>, const std::string &, Nan::FunctionCallback); static void setup_static_method(v8::Local<v8::FunctionTemplate>, const std::string &, v8::FunctionCallback);
template<typename TargetType> template<typename TargetType>
static void setup_property(v8::Local<TargetType>, const std::string &, const PropertyType &); static void setup_property(v8::Local<TargetType>, const std::string &, const PropertyType &);
static void construct(Nan::NAN_METHOD_ARGS_TYPE); static void get_indexes(const v8::PropertyCallbackInfo<v8::Array>&);
static void get_indexes(Nan::NAN_INDEX_ENUMERATOR_ARGS_TYPE); static void set_property(v8::Local<v8::String>, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&);
static void set_property(v8::Local<v8::String>, v8::Local<v8::Value>, Nan::NAN_PROPERTY_SETTER_ARGS_TYPE);
static void set_readonly_property(v8::Local<v8::String> property, v8::Local<v8::Value> value, Nan::NAN_SETTER_ARGS_TYPE info) { static void set_readonly_property(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) {
std::string message = std::string("Cannot assign to read only property '") + std::string(String(property)) + "'"; std::string message = std::string("Cannot assign to read only property '") + std::string(String(property)) + "'";
Nan::ThrowError(message.c_str()); Nan::ThrowError(message.c_str());
} }
static void set_readonly_index(uint32_t index, v8::Local<v8::Value> value, Nan::NAN_INDEX_SETTER_ARGS_TYPE info) { static void set_readonly_index(uint32_t index, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) {
std::string message = std::string("Cannot assign to read only index ") + util::to_string(index); std::string message = std::string("Cannot assign to read only index ") + util::to_string(index);
Nan::ThrowError(message.c_str()); Nan::ThrowError(message.c_str());
} }
static void get_nonexistent_property(v8::Local<v8::String>, Nan::NAN_PROPERTY_GETTER_ARGS_TYPE) { static void get_nonexistent_property(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>&) {
// Do nothing. This function exists only to prevent a crash where it is used. // Do nothing. This function exists only to prevent a crash where it is used.
} }
}; };
@ -109,7 +110,7 @@ class ObjectWrap<void> {
}; };
// This helper function is needed outside the scope of the ObjectWrap class as well. // This helper function is needed outside the scope of the ObjectWrap class as well.
static inline std::vector<v8::Local<v8::Value>> get_arguments(const Nan::FunctionCallbackInfo<v8::Value> &info) { static inline std::vector<v8::Local<v8::Value>> get_arguments(const v8::FunctionCallbackInfo<v8::Value> &info) {
int count = info.Length(); int count = info.Length();
std::vector<v8::Local<v8::Value>> arguments; std::vector<v8::Local<v8::Value>> arguments;
arguments.reserve(count); arguments.reserve(count);
@ -156,7 +157,7 @@ template<typename ClassType>
inline v8::Local<v8::FunctionTemplate> ObjectWrap<ClassType>::create_template() { inline v8::Local<v8::FunctionTemplate> ObjectWrap<ClassType>::create_template() {
Nan::EscapableHandleScope scope; Nan::EscapableHandleScope scope;
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(construct); v8::Local<v8::FunctionTemplate> tpl = v8::FunctionTemplate::New(v8::Isolate::GetCurrent(), construct);
v8::Local<v8::ObjectTemplate> instance_tpl = tpl->InstanceTemplate(); v8::Local<v8::ObjectTemplate> instance_tpl = tpl->InstanceTemplate();
v8::Local<v8::String> name = Nan::New(s_class.name).ToLocalChecked(); v8::Local<v8::String> name = Nan::New(s_class.name).ToLocalChecked();
@ -181,21 +182,21 @@ inline v8::Local<v8::FunctionTemplate> ObjectWrap<ClassType>::create_template()
if (s_class.index_accessor.getter) { if (s_class.index_accessor.getter) {
auto &index_accessor = s_class.index_accessor; auto &index_accessor = s_class.index_accessor;
Nan::SetIndexedPropertyHandler(instance_tpl, index_accessor.getter, index_accessor.setter ?: set_readonly_index, 0, 0, get_indexes); instance_tpl->SetIndexedPropertyHandler(index_accessor.getter, index_accessor.setter ?: set_readonly_index, 0, 0, get_indexes);
} }
if (s_class.string_accessor.getter || s_class.index_accessor.getter || s_class.index_accessor.setter) { if (s_class.string_accessor.getter || s_class.index_accessor.getter || s_class.index_accessor.setter) {
// Use our own wrapper for the setter since we want to throw for negative indices. // Use our own wrapper for the setter since we want to throw for negative indices.
auto &string_accessor = s_class.string_accessor; auto &string_accessor = s_class.string_accessor;
Nan::SetNamedPropertyHandler(instance_tpl, string_accessor.getter ?: get_nonexistent_property, set_property, 0, 0, string_accessor.enumerator); instance_tpl->SetNamedPropertyHandler(string_accessor.getter ?: get_nonexistent_property, set_property, 0, 0, string_accessor.enumerator);
} }
return scope.Escape(tpl); return scope.Escape(tpl);
} }
template<typename ClassType> template<typename ClassType>
inline void ObjectWrap<ClassType>::setup_method(v8::Local<v8::FunctionTemplate> tpl, const std::string &name, Nan::FunctionCallback callback) { inline void ObjectWrap<ClassType>::setup_method(v8::Local<v8::FunctionTemplate> tpl, const std::string &name, v8::FunctionCallback callback) {
v8::Local<v8::Signature> signature = Nan::New<v8::Signature>(tpl); v8::Local<v8::Signature> signature = Nan::New<v8::Signature>(tpl);
v8::Local<v8::FunctionTemplate> fn_tpl = Nan::New<v8::FunctionTemplate>(callback, v8::Local<v8::Value>(), signature); v8::Local<v8::FunctionTemplate> fn_tpl = v8::FunctionTemplate::New(v8::Isolate::GetCurrent(), callback, v8::Local<v8::Value>(), signature);
v8::Local<v8::String> fn_name = Nan::New(name).ToLocalChecked(); v8::Local<v8::String> fn_name = Nan::New(name).ToLocalChecked();
// The reason we use this rather than Nan::SetPrototypeMethod is DontEnum. // The reason we use this rather than Nan::SetPrototypeMethod is DontEnum.
@ -204,8 +205,8 @@ inline void ObjectWrap<ClassType>::setup_method(v8::Local<v8::FunctionTemplate>
} }
template<typename ClassType> template<typename ClassType>
inline void ObjectWrap<ClassType>::setup_static_method(v8::Local<v8::FunctionTemplate> tpl, const std::string &name, Nan::FunctionCallback callback) { inline void ObjectWrap<ClassType>::setup_static_method(v8::Local<v8::FunctionTemplate> tpl, const std::string &name, v8::FunctionCallback callback) {
v8::Local<v8::FunctionTemplate> fn_tpl = Nan::New<v8::FunctionTemplate>(callback); v8::Local<v8::FunctionTemplate> fn_tpl = v8::FunctionTemplate::New(v8::Isolate::GetCurrent(), callback);
v8::Local<v8::String> fn_name = Nan::New(name).ToLocalChecked(); v8::Local<v8::String> fn_name = Nan::New(name).ToLocalChecked();
tpl->Set(fn_name, fn_tpl, v8::PropertyAttribute::DontEnum); tpl->Set(fn_name, fn_tpl, v8::PropertyAttribute::DontEnum);
@ -218,11 +219,11 @@ inline void ObjectWrap<ClassType>::setup_property(v8::Local<TargetType> target,
v8::Local<v8::String> prop_name = Nan::New(name).ToLocalChecked(); v8::Local<v8::String> prop_name = Nan::New(name).ToLocalChecked();
v8::PropertyAttribute attributes = v8::PropertyAttribute(v8::DontEnum | v8::DontDelete); v8::PropertyAttribute attributes = v8::PropertyAttribute(v8::DontEnum | v8::DontDelete);
Nan::SetAccessor(target, prop_name, property.getter, property.setter ?: set_readonly_property, v8::Local<v8::Value>(), v8::DEFAULT, attributes); target->SetAccessor(prop_name, property.getter, property.setter ?: set_readonly_property, v8::Local<v8::Value>(), v8::DEFAULT, attributes);
} }
template<typename ClassType> template<typename ClassType>
inline void ObjectWrap<ClassType>::construct(Nan::NAN_METHOD_ARGS_TYPE info) { inline void ObjectWrap<ClassType>::construct(const v8::FunctionCallbackInfo<v8::Value>& info) {
if (!info.IsConstructCall()) { if (!info.IsConstructCall()) {
Nan::ThrowError("Constructor must be called with new"); Nan::ThrowError("Constructor must be called with new");
} }
@ -248,7 +249,7 @@ inline void ObjectWrap<ClassType>::construct(Nan::NAN_METHOD_ARGS_TYPE info) {
} }
template<typename ClassType> template<typename ClassType>
inline void ObjectWrap<ClassType>::get_indexes(Nan::NAN_INDEX_ENUMERATOR_ARGS_TYPE info) { inline void ObjectWrap<ClassType>::get_indexes(const v8::PropertyCallbackInfo<v8::Array>& info) {
uint32_t length; uint32_t length;
try { try {
length = Object::validated_get_length(info.GetIsolate(), info.This()); length = Object::validated_get_length(info.GetIsolate(), info.This());
@ -267,7 +268,7 @@ inline void ObjectWrap<ClassType>::get_indexes(Nan::NAN_INDEX_ENUMERATOR_ARGS_TY
} }
template<typename ClassType> template<typename ClassType>
inline void ObjectWrap<ClassType>::set_property(v8::Local<v8::String> property, v8::Local<v8::Value> value, Nan::NAN_PROPERTY_SETTER_ARGS_TYPE info) { inline void ObjectWrap<ClassType>::set_property(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) {
if (s_class.index_accessor.getter || s_class.index_accessor.setter) { if (s_class.index_accessor.getter || s_class.index_accessor.setter) {
try { try {
// Negative indices are passed into this string property interceptor, so check for them here. // Negative indices are passed into this string property interceptor, so check for them here.
@ -294,7 +295,7 @@ template<typename ClassType>
class ObjectWrap<node::Types, ClassType> : public node::ObjectWrap<ClassType> {}; class ObjectWrap<node::Types, ClassType> : public node::ObjectWrap<ClassType> {};
template<node::MethodType F> template<node::MethodType F>
void wrap(Nan::NAN_METHOD_ARGS_TYPE info) { void wrap(const v8::FunctionCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate(); v8::Isolate* isolate = info.GetIsolate();
node::ReturnValue return_value(info.GetReturnValue()); node::ReturnValue return_value(info.GetReturnValue());
auto arguments = node::get_arguments(info); auto arguments = node::get_arguments(info);
@ -308,7 +309,7 @@ void wrap(Nan::NAN_METHOD_ARGS_TYPE info) {
} }
template<node::PropertyType::GetterType F> template<node::PropertyType::GetterType F>
void wrap(v8::Local<v8::String> property, Nan::NAN_GETTER_ARGS_TYPE info) { void wrap(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate(); v8::Isolate* isolate = info.GetIsolate();
node::ReturnValue return_value(info.GetReturnValue()); node::ReturnValue return_value(info.GetReturnValue());
try { try {
@ -320,7 +321,7 @@ void wrap(v8::Local<v8::String> property, Nan::NAN_GETTER_ARGS_TYPE info) {
} }
template<node::PropertyType::SetterType F> template<node::PropertyType::SetterType F>
void wrap(v8::Local<v8::String> property, v8::Local<v8::Value> value, Nan::NAN_SETTER_ARGS_TYPE info) { void wrap(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) {
v8::Isolate* isolate = info.GetIsolate(); v8::Isolate* isolate = info.GetIsolate();
try { try {
F(isolate, info.This(), value); F(isolate, info.This(), value);
@ -331,7 +332,7 @@ void wrap(v8::Local<v8::String> property, v8::Local<v8::Value> value, Nan::NAN_S
} }
template<node::IndexPropertyType::GetterType F> template<node::IndexPropertyType::GetterType F>
void wrap(uint32_t index, Nan::NAN_INDEX_GETTER_ARGS_TYPE info) { void wrap(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate(); v8::Isolate* isolate = info.GetIsolate();
node::ReturnValue return_value(info.GetReturnValue()); node::ReturnValue return_value(info.GetReturnValue());
try { try {
@ -347,7 +348,7 @@ void wrap(uint32_t index, Nan::NAN_INDEX_GETTER_ARGS_TYPE info) {
} }
template<node::IndexPropertyType::SetterType F> template<node::IndexPropertyType::SetterType F>
void wrap(uint32_t index, v8::Local<v8::Value> value, Nan::NAN_INDEX_SETTER_ARGS_TYPE info) { void wrap(uint32_t index, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate(); v8::Isolate* isolate = info.GetIsolate();
try { try {
if (F(isolate, info.This(), index, value)) { if (F(isolate, info.This(), index, value)) {
@ -361,7 +362,7 @@ void wrap(uint32_t index, v8::Local<v8::Value> value, Nan::NAN_INDEX_SETTER_ARGS
} }
template<node::StringPropertyType::GetterType F> template<node::StringPropertyType::GetterType F>
void wrap(v8::Local<v8::String> property, Nan::NAN_PROPERTY_GETTER_ARGS_TYPE info) { void wrap(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate(); v8::Isolate* isolate = info.GetIsolate();
node::ReturnValue return_value(info.GetReturnValue()); node::ReturnValue return_value(info.GetReturnValue());
try { try {
@ -373,7 +374,7 @@ void wrap(v8::Local<v8::String> property, Nan::NAN_PROPERTY_GETTER_ARGS_TYPE inf
} }
template<node::StringPropertyType::SetterType F> template<node::StringPropertyType::SetterType F>
void wrap(v8::Local<v8::String> property, v8::Local<v8::Value> value, Nan::NAN_PROPERTY_SETTER_ARGS_TYPE info) { void wrap(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate(); v8::Isolate* isolate = info.GetIsolate();
try { try {
if (F(isolate, info.This(), property, value)) { if (F(isolate, info.This(), property, value)) {
@ -387,7 +388,7 @@ void wrap(v8::Local<v8::String> property, v8::Local<v8::Value> value, Nan::NAN_P
} }
template<node::StringPropertyType::EnumeratorType F> template<node::StringPropertyType::EnumeratorType F>
void wrap(Nan::NAN_PROPERTY_ENUMERATOR_ARGS_TYPE info) { void wrap(const v8::PropertyCallbackInfo<v8::Array>& info) {
auto names = F(info.GetIsolate(), info.This()); auto names = F(info.GetIsolate(), info.This());
int count = (int)names.size(); int count = (int)names.size();
v8::Local<v8::Array> array = Nan::New<v8::Array>(count); v8::Local<v8::Array> array = Nan::New<v8::Array>(count);

View File

@ -17,6 +17,7 @@
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
#include "node_init.hpp" #include "node_init.hpp"
#include "js_realm.hpp"
namespace realm { namespace realm {
namespace node { namespace node {

View File

@ -27,5 +27,3 @@
#include "node_exception.hpp" #include "node_exception.hpp"
#include "node_return_value.hpp" #include "node_return_value.hpp"
#include "node_object_accessor.hpp" #include "node_object_accessor.hpp"
#include "js_realm.hpp"

View File

@ -155,5 +155,15 @@ inline void node::Object::set_internal(const v8::Local<v8::Object> &object, type
*wrap = ptr; *wrap = ptr;
} }
template<>
inline void node::Object::set_global(v8::Isolate* isolate, const node::String &key, const v8::Local<v8::Value> &value) {
Object::set_property(isolate, isolate->GetCurrentContext()->Global(), key, value);
}
template<>
inline v8::Local<v8::Value> node::Object::get_global(v8::Isolate* isolate, const node::String &key) {
return Object::get_property(isolate, isolate->GetCurrentContext()->Global(), key);
}
} // js } // js
} // realm } // realm

View File

@ -35,7 +35,7 @@ class Protected {
operator v8::Local<MemberType>() const { operator v8::Local<MemberType>() const {
return Nan::New(m_value); return Nan::New(m_value);
} }
operator bool() const { explicit operator bool() const {
return m_value.isEmpty(); return m_value.isEmpty();
} }
bool operator==(const v8::Local<MemberType> &other) const { bool operator==(const v8::Local<MemberType> &other) const {
@ -50,6 +50,12 @@ class Protected {
bool operator!=(const Protected<MemberType> &other) const { bool operator!=(const Protected<MemberType> &other) const {
return m_value != other.m_value; return m_value != other.m_value;
} }
struct Comparator {
bool operator()(const Protected<MemberType>& a, const Protected<MemberType>& b) const {
return Nan::New(a.m_value)->StrictEquals(Nan::New(b.m_value));
}
};
}; };
} // node } // node
@ -88,5 +94,13 @@ class Protected<node::Types::Function> : public node::Protected<v8::Function> {
Protected(v8::Isolate* isolate, v8::Local<v8::Function> object) : node::Protected<v8::Function>(object) {} Protected(v8::Isolate* isolate, v8::Local<v8::Function> object) : node::Protected<v8::Function>(object) {}
}; };
template<typename T>
struct GlobalCopyablePersistentTraits {
typedef v8::Persistent<T, GlobalCopyablePersistentTraits<T>> CopyablePersistent;
static const bool kResetInDestructor = false;
template<typename S, typename M>
static inline void Copy(const v8::Persistent<S, M> &source, CopyablePersistent *dest) {}
};
} // js } // js
} // realm } // realm

View File

@ -25,10 +25,10 @@ namespace js {
template<> template<>
class ReturnValue<node::Types> { class ReturnValue<node::Types> {
Nan::ReturnValue<v8::Value> m_value; v8::ReturnValue<v8::Value> m_value;
public: public:
ReturnValue(Nan::ReturnValue<v8::Value> value) : m_value(value) {} ReturnValue(v8::ReturnValue<v8::Value> value) : m_value(value) {}
void set(const v8::Local<v8::Value> &value) { void set(const v8::Local<v8::Value> &value) {
m_value.Set(value); m_value.Set(value);

View File

@ -23,7 +23,10 @@
#include <map> #include <map>
#include <string> #include <string>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wundef"
#include <nan.h> #include <nan.h>
#pragma GCC diagnostic pop
#include "js_types.hpp" #include "js_types.hpp"
@ -31,6 +34,8 @@
#define REALM_V8_ARRAY_BUFFER_API 1 #define REALM_V8_ARRAY_BUFFER_API 1
#endif #endif
#define HANDLESCOPE Nan::HandleScope handle_scope;
namespace realm { namespace realm {
namespace node { namespace node {
@ -42,15 +47,15 @@ struct Types {
using String = v8::Local<v8::String>; using String = v8::Local<v8::String>;
using Function = v8::Local<v8::Function>; using Function = v8::Local<v8::Function>;
using ConstructorCallback = Nan::FunctionCallback; using ConstructorCallback = v8::FunctionCallback;
using FunctionCallback = Nan::FunctionCallback; using FunctionCallback = v8::FunctionCallback;
using PropertyGetterCallback = Nan::GetterCallback; using PropertyGetterCallback = v8::AccessorGetterCallback;
using PropertySetterCallback = Nan::SetterCallback; using PropertySetterCallback = v8::AccessorSetterCallback;
using IndexPropertyGetterCallback = Nan::IndexGetterCallback; using IndexPropertyGetterCallback = v8::IndexedPropertyGetterCallback;
using IndexPropertySetterCallback = Nan::IndexSetterCallback; using IndexPropertySetterCallback = v8::IndexedPropertySetterCallback;
using StringPropertyGetterCallback = Nan::PropertyGetterCallback; using StringPropertyGetterCallback = v8::NamedPropertyGetterCallback;
using StringPropertySetterCallback = Nan::PropertySetterCallback; using StringPropertySetterCallback = v8::NamedPropertySetterCallback;
using StringPropertyEnumeratorCallback = Nan::PropertyEnumeratorCallback; using StringPropertyEnumeratorCallback = v8::NamedPropertyEnumeratorCallback;
}; };
template<typename ClassType> template<typename ClassType>

View File

@ -129,7 +129,7 @@ inline bool node::Value::to_boolean(v8::Isolate* isolate, const v8::Local<v8::Va
template<> template<>
inline double node::Value::to_number(v8::Isolate* isolate, const v8::Local<v8::Value> &value) { inline double node::Value::to_number(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
double number = Nan::To<double>(value).FromMaybe(NAN); double number = Nan::To<double>(value).FromMaybe(NAN);
if (isnan(number)) { if (std::isnan(number)) {
throw std::invalid_argument("Value not convertible to a number."); throw std::invalid_argument("Value not convertible to a number.");
} }
return number; return number;

@ -1 +1 @@
Subproject commit c3e4be6d6cd0bf3e010e169b9793087e60eb52bb Subproject commit 1c2f3a7607467ed904a81a4824d0cbda33cc0ebb

View File

@ -1,7 +1,9 @@
{ {
"env": { "env": {
"commonjs": true "jasmine": true
}, },
"plugins": ["jasmine"],
"extends": "plugin:jasmine/recommended",
"globals": { "globals": {
"ArrayBuffer": false, "ArrayBuffer": false,
"DataView": false, "DataView": false,
@ -14,5 +16,12 @@
"Uint32Array": false, "Uint32Array": false,
"Uint8Array": false, "Uint8Array": false,
"Uint8ClampedArray": false "Uint8ClampedArray": false
},
"rules": {
"no-invalid-this": "off",
"no-magic-numbers": "off",
"jasmine/no-spec-dupes": ["error", "branch"],
"jasmine/no-suite-dupes": ["error", "branch"],
"no-console": "off"
} }
} }

2
tests/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/sync-bundle/
/junitresults-*.xml

View File

@ -23,14 +23,13 @@
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
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({ RealmTests.registerTests({
WorkerTests: require('./js/worker-tests'), AsyncTests: require('./js/async-tests'),
}); });
const testNames = RealmTests.getTestNames(); const testNames = RealmTests.getTestNames();
@ -79,10 +78,6 @@ function runTests() {
} }
if (require.main == module) { if (require.main == module) {
mockery.enable();
mockery.warnOnUnregistered(false);
mockery.registerMock('realm', require('..'));
runTests().then( runTests().then(
(passed) => { (passed) => {
if (!passed) { if (!passed) {

View File

@ -27,5 +27,6 @@
- (JSValue *)loadModuleFromURL:(NSURL *)url error:(NSError **)error; - (JSValue *)loadModuleFromURL:(NSURL *)url error:(NSError **)error;
- (JSValue *)loadJSONFromURL:(NSURL *)url error:(NSError **)error; - (JSValue *)loadJSONFromURL:(NSURL *)url error:(NSError **)error;
- (JSValue *)loadGlobalModule:(NSString *)name relativeToURL:(NSURL *)url error:(NSError **)error;
@end @end

View File

@ -75,6 +75,9 @@ static NSString * const RJSModuleLoaderErrorDomain = @"RJSModuleLoaderErrorDomai
- (JSValue *)loadModuleFromURL:(NSURL *)url error:(NSError **)error { - (JSValue *)loadModuleFromURL:(NSURL *)url error:(NSError **)error {
url = url.absoluteURL; url = url.absoluteURL;
url = url.standardizedURL ?: url; url = url.standardizedURL ?: url;
if (url.pathExtension.length == 0) {
url = [url URLByAppendingPathExtension:@"js"];
}
NSString *path = url.path; NSString *path = url.path;
JSValue *exports = self.modules[path]; JSValue *exports = self.modules[path];
@ -156,6 +159,9 @@ static NSString * const RJSModuleLoaderErrorDomain = @"RJSModuleLoaderErrorDomai
- (JSValue *)loadJSONFromURL:(NSURL *)url error:(NSError **)error { - (JSValue *)loadJSONFromURL:(NSURL *)url error:(NSError **)error {
url = url.absoluteURL; url = url.absoluteURL;
url = url.standardizedURL ?: url; url = url.standardizedURL ?: url;
if (url.pathExtension.length == 0) {
url = [url URLByAppendingPathExtension:@"js"];
}
NSString *path = url.path; NSString *path = url.path;
JSValue *exports = self.modules[path]; JSValue *exports = self.modules[path];
@ -195,6 +201,18 @@ static NSString * const RJSModuleLoaderErrorDomain = @"RJSModuleLoaderErrorDomai
BOOL isDirectory; BOOL isDirectory;
if ([fileManager fileExistsAtPath:moduleURL.path isDirectory:&isDirectory] && isDirectory) { if ([fileManager fileExistsAtPath:moduleURL.path isDirectory:&isDirectory] && isDirectory) {
NSURL *packageURL = [moduleURL URLByAppendingPathComponent:@"package.json"];
NSDictionary *package;
if ([fileManager fileExistsAtPath:packageURL.path]) {
NSError *error;
NSData *data = [NSData dataWithContentsOfURL:packageURL options:0 error:&error];
package = data ? [NSJSONSerialization JSONObjectWithData:data options:0 error:&error] : nil;
NSAssert(package, @"%@", error);
}
moduleURL = [moduleURL URLByAppendingPathComponent:package[@"main"] ?: @"index.js"];
return [self loadModuleFromURL:moduleURL error:error]; return [self loadModuleFromURL:moduleURL error:error];
} }

View File

@ -31,12 +31,23 @@
+ (XCTestSuite *)defaultTestSuite { + (XCTestSuite *)defaultTestSuite {
XCTestSuite *suite = [super defaultTestSuite]; XCTestSuite *suite = [super defaultTestSuite];
JSContext *context = [[JSContext alloc] init];
// We need a JS context from a UIWebView so it has setTimeout, Promise, etc.
UIWebView *webView = [[UIWebView alloc] init];
JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
RJSModuleLoader *moduleLoader = [[RJSModuleLoader alloc] initWithContext:context]; RJSModuleLoader *moduleLoader = [[RJSModuleLoader alloc] initWithContext:context];
NSURL *realmURL = [[NSBundle bundleForClass:self] URLForResource:@"index" withExtension:@"js" subdirectory:@"lib"]; NSURL *realmURL = [[NSBundle bundleForClass:self] URLForResource:@"index" withExtension:@"js" subdirectory:@"lib"];
NSURL *scriptURL = [[NSBundle bundleForClass:self] URLForResource:@"index" withExtension:@"js" subdirectory:@"js"]; NSURL *scriptURL = [[NSBundle bundleForClass:self] URLForResource:@"index" withExtension:@"js" subdirectory:@"js"];
NSError *error; NSError *error;
// The ES6 global Promise constructor was added in iOS 8.
if (![context[@"Promise"] isObject]) {
JSValue *promiseModule = [moduleLoader loadGlobalModule:@"es6-promise" relativeToURL:scriptURL error:&error];
NSAssert(promiseModule, @"%@", error);
context[@"Promise"] = promiseModule[@"Promise"];
}
// Create Realm constructor in the JS context. // Create Realm constructor in the JS context.
RJSInitializeInContext(context.JSGlobalContextRef); RJSInitializeInContext(context.JSGlobalContextRef);
@ -73,10 +84,32 @@
JSContext *context = testObject.context; JSContext *context = testObject.context;
context.exception = nil; context.exception = nil;
[testObject invokeMethod:@"runTest" withArguments:@[NSStringFromClass(self.class), method]]; JSValue *promise = [testObject invokeMethod:@"runTest" withArguments:@[NSStringFromClass(self.class), method]];
JSValue *exception = context.exception; if (context.exception) {
if (exception) { [self recordException:context.exception];
return;
}
if ([promise isObject]) {
XCTestExpectation *expectation = [self expectationWithDescription:@"Promise resolved or rejected"];
JSValue *onFulfilled = [JSValue valueWithObject:^() {
[expectation fulfill];
} inContext:context];
JSValue *onRejected = [JSValue valueWithObject:^(JSValue *error) {
[self recordException:error];
[expectation fulfill];
} inContext:context];
[promise invokeMethod:@"then" withArguments:@[onFulfilled, onRejected]];
[self waitForExpectationsWithTimeout:5.0 handler:NULL];
}
}
- (void)recordException:(JSValue *)exception {
JSValue *message = [exception hasProperty:@"message"] ? exception[@"message"] : exception; JSValue *message = [exception hasProperty:@"message"] ? exception[@"message"] : exception;
NSString *source = [exception hasProperty:@"sourceURL"] ? [exception[@"sourceURL"] toString] : nil; NSString *source = [exception hasProperty:@"sourceURL"] ? [exception[@"sourceURL"] toString] : nil;
NSUInteger line = [exception hasProperty:@"line"] ? [exception[@"line"] toUInt32] - 1 : 0; NSUInteger line = [exception hasProperty:@"line"] ? [exception[@"line"] toUInt32] - 1 : 0;
@ -91,7 +124,6 @@
inFile:sourceURL ? sourceURL.absoluteString : @(__FILE__) inFile:sourceURL ? sourceURL.absoluteString : @(__FILE__)
atLine:sourceURL ? line : __LINE__ atLine:sourceURL ? line : __LINE__
expected:YES]; expected:YES];
}
} }
@end @end

View File

@ -49,6 +49,19 @@ module.exports = {
} }
}, },
assertArray: function(value, length, errorMessage) {
if (!Array.isArray(value)) {
throw new TestFailureError(errorMessage || `Value ${value} is not an array`);
}
},
assertArrayLength: function(value, length, errorMessage) {
this.assertArray(value);
if (value.length !== length) {
throw new TestFailureError(errorMessage || `Value ${value} is not an array of length ${length}`);
}
},
assertArraysEqual: function(val1, val2, errorMessage) { assertArraysEqual: function(val1, val2, errorMessage) {
var len1 = val1.length; var len1 = val1.length;
var len2 = val2.length; var len2 = val2.length;
@ -106,7 +119,23 @@ module.exports = {
assertTrue: function(condition, errorMessage) { assertTrue: function(condition, errorMessage) {
if (!condition) { if (!condition) {
throw new TestFailureError(errorMessage || 'Condition expected to be true'); throw new TestFailureError(errorMessage || `Condition ${condition} expected to be true`);
}
},
assertInstanceOf: function(object, type, errorMessage) {
if (!(object instanceof type)) {
throw new TestFailureError(errorMessage || `Object ${object} expected to be of type ${type}`);
}
},
assertType: function(value, type) {
this.assertEqual(typeof value, type, `Value ${value} expected to be of type ${type}`);
},
assertUndefined: function(value, errorMessage) {
if (value !== undefined) {
throw new TestFailureError(errorMessage || `Value ${value} expected to be undefined`);
} }
}, },

360
tests/js/async-tests.js Normal file
View File

@ -0,0 +1,360 @@
////////////////////////////////////////////////////////////////////////////
//
// 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');
function createNotificationTest(config, getObservable, addListener, removeListener, messages, expectedCount) {
return new Promise((resolve, reject) => {
let realm = new Realm(config);
let observable = getObservable(realm);
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'));
}, 5000);
let cleanup = () => {
clearTimeout(timer);
worker.terminate();
};
var count = 0;
var listener = addListener(observable, () => count++, resolve, reject, cleanup);
messages.push(['echo', 'resolve']);
var messageIndex = 0;
worker.onmessage = (message) => {
if (message.error) {
reject(message.error);
cleanup();
}
else if (message.result == 'resolve') {
if (count != expectedCount) {
reject('Notification count ' + count + ' not equal to expected count ' + expectedCount);
}
else {
resolve();
}
cleanup();
}
else {
if (message.result == 'removeListener') {
removeListener(observable, listener);
}
worker.postMessage(messages[messageIndex++]);
}
};
worker.postMessage(messages[messageIndex++]);
});
}
function createCollectionChangeTest(config, createCollection, messages, expected, removeAll) {
return createNotificationTest(
config,
createCollection,
(collection, increment, resolve, reject, cleanup) => {
var listener = (object, changes) => {
try {
var notificationCount = increment();
TestCase.assertArraysEqual(changes.insertions, expected[notificationCount][0]);
TestCase.assertArraysEqual(changes.deletions, expected[notificationCount][1]);
TestCase.assertArraysEqual(changes.modifications, expected[notificationCount][2]);
} catch (e) {
reject(e);
cleanup();
}
};
collection.addListener(listener);
return listener;
},
removeAll ? (observable) => observable.removeAllListeners() :
(observable, listener) => observable.removeListener(listener),
messages,
expected.length
);
}
const ListObject = {
name: 'ListObject',
properties: {
list: {type: 'list', objectType: 'TestObject'},
}
};
const PrimaryListObject = {
name: 'PrimaryListObject',
properties: {
list: {type: 'list', objectType: 'IntPrimaryObject'},
}
};
module.exports = {
testChangeNotifications() {
var config = { schema: [schemas.TestObject] };
return createNotificationTest(
config,
(realm) => realm,
(realm, increment, resolve, reject, cleanup) => realm.addListener('change', () => {
try {
var objects = realm.objects('TestObject');
TestCase.assertEqual(objects.length, 1);
TestCase.assertEqual(objects[0].doubleCol, 42);
increment();
} catch (e) {
reject(e);
cleanup();
}
}),
undefined,
[[config, 'create', 'TestObject', [{doubleCol: 42}]]],
1
);
},
testResultsAddNotifications() {
var config = { schema: [schemas.TestObject] };
return createCollectionChangeTest(
config,
(realm) => realm.objects('TestObject'),
[
[config, 'create', 'TestObject', [{ doubleCol: 1 }]],
[config, 'create', 'TestObject', [{ doubleCol: 2 }, { doubleCol: 3 }]]
],
[
[[], [], []],
[[0], [], []],
[[1, 2], [], []],
]
);
},
testResultsRemoveNotifications() {
var config = { schema: [schemas.TestObject] };
return createCollectionChangeTest(
config,
(realm) => realm.objects('TestObject'),
[
[config, 'create', 'TestObject', [{ doubleCol: 1 }]],
['echo', 'removeListener'],
[config, 'create', 'TestObject', [{ doubleCol: 2 }, { doubleCol: 3 }]]
],
[
[[], [], []],
[[0], [], []],
]
);
},
testResultsRemoveAllNotifications() {
var config = { schema: [schemas.TestObject] };
return createCollectionChangeTest(
config,
(realm) => realm.objects('TestObject'),
[
[config, 'create', 'TestObject', [{ doubleCol: 1 }]],
['echo', 'removeListener'],
[config, 'create', 'TestObject', [{ doubleCol: 2 }, { doubleCol: 3 }]]
],
[
[[], [], []],
[[0], [], []],
],
true
);
},
testResultsDeleteNotifications() {
var config = { schema: [schemas.TestObject] };
return createCollectionChangeTest(
config,
function(realm) {
return realm.objects('TestObject');
},
[
[config, 'create', 'TestObject', [[0], [1], [2], [3], [4]]],
[config, 'delete', 'TestObject', [4]],
[config, 'delete', 'TestObject', [0, 2]]
],
[
[[], [], []],
[[0, 1, 2, 3, 4], [], []],
[[], [4], []],
[[0], [0, 2, 3], []]
]
);
},
testResultsUpdateNotifications() {
var config = { schema: [schemas.IntPrimary] };
return createCollectionChangeTest(
config,
(realm) => realm.objects('IntPrimaryObject'),
[
[config, 'create', 'IntPrimaryObject', [[0, '0'], [1, '1'], [2, '2']]],
[config, 'update', 'IntPrimaryObject', [[0, '00'], [2, '22']]]
],
[
[[], [], []],
[[0, 1, 2], [], []],
[[], [], [0, 2]]
]
);
},
testListAddNotifications() {
var config = { schema: [schemas.TestObject, ListObject] };
return createCollectionChangeTest(
config,
function(realm) {
let listObject;
realm.write(() => {
listObject = realm.create('ListObject', {list: []})
});
return listObject.list;
},
[
[config, 'list_method', 'ListObject', 'list', 'push', {doubleCol: 0}, {doubleCol: 1}]
],
[
[[], [], []],
[[0, 1], [], []]
]
);
},
testListRemoveNotifications() {
var config = { schema: [schemas.TestObject, ListObject] };
return createCollectionChangeTest(
config,
function(realm) {
let listObject;
realm.write(() => {
listObject = realm.create('ListObject', {list: []})
});
return listObject.list;
},
[
[config, 'list_method', 'ListObject', 'list', 'push', {doubleCol: 0}, {doubleCol: 1}],
['echo', 'removeListener'],
[config, 'list_method', 'ListObject', 'list', 'push', {doubleCol: 0}, {doubleCol: 1}],
],
[
[[], [], []],
[[0, 1], [], []]
]
);
},
testListRemoveAllNotifications() {
var config = { schema: [schemas.TestObject, ListObject] };
return createCollectionChangeTest(
config,
function(realm) {
let listObject;
realm.write(() => {
listObject = realm.create('ListObject', {list: []})
});
return listObject.list;
},
[
[config, 'list_method', 'ListObject', 'list', 'push', {doubleCol: 0}, {doubleCol: 1}],
['echo', 'removeListener'],
[config, 'list_method', 'ListObject', 'list', 'push', {doubleCol: 0}, {doubleCol: 1}],
],
[
[[], [], []],
[[0, 1], [], []]
],
true
);
},
testListDeleteNotifications() {
var config = { schema: [schemas.TestObject, ListObject] };
return createCollectionChangeTest(
config,
function(realm) {
let listObject;
realm.write(() => {
listObject = realm.create('ListObject', {list: [[0], [1], [2]]})
});
return listObject.list;
},
[
[config, 'list_method', 'ListObject', 'list', 'splice', 1, 2]
],
[
[[], [], []],
[[], [1, 2], []]
]
);
},
testListSpliceNotifications() {
var config = { schema: [schemas.TestObject, ListObject] };
return createCollectionChangeTest(
config,
function(realm) {
let listObject;
realm.write(() => {
listObject = realm.create('ListObject', {list: [[0], [1], [2]]})
});
return listObject.list;
},
[
[config, 'list_method', 'ListObject', 'list', 'splice', 1, 1, [2]]
],
[
[[], [], []],
[[1], [1], []]
]
);
},
testListUpdateNotifications() {
var config = { schema: [schemas.IntPrimary, PrimaryListObject] };
return createCollectionChangeTest(
config,
function(realm) {
let listObject;
realm.write(() => {
listObject = realm.create('PrimaryListObject', {list: [[0, '0'], [1, '1']]})
});
return listObject.list;
},
[
[config, 'update', 'IntPrimaryObject', [[1, '11']]]
],
[
[[], [], []],
[[], [], [1]]
]
);
},
};

View File

@ -1,5 +1,8 @@
{ {
"name": "realm-tests", "name": "realm-tests",
"version": "0.0.1", "version": "0.0.1",
"private": true "private": true,
"dependencies": {
"es6-promise": "^3.2.1"
}
} }

View File

@ -1 +0,0 @@
../../src/object-store/tests/query.json

381
tests/js/query-tests.json Normal file
View File

@ -0,0 +1,381 @@
{
"dateTests" : {
"schema" : [{
"name": "DateObject",
"properties": [{ "name": "date", "type": "date" }]
}],
"objects": [
{ "type": "DateObject", "value": [10000] },
{ "type": "DateObject", "value": [10001] },
{ "type": "DateObject", "value": [10002] }
],
"tests": [
["QueryCount", 2, "DateObject", "date < $0", [2, "date"]],
["QueryCount", 3, "DateObject", "date <= $0", [2, "date"]],
["QueryCount", 2, "DateObject", "date > $0", [0, "date"]],
["QueryCount", 3, "DateObject", "date >= $0", [0, "date"]],
["QueryCount", 1, "DateObject", "date == $0", [0, "date"]],
["QueryCount", 2, "DateObject", "date != $0", [0, "date"]],
["QueryThrows", "DateObject", "date == 'not a date'"],
["QueryThrows", "DateObject", "date == 1"],
["QueryThrows", "DateObject", "date == $0", 1]
]
},
"boolTests" : {
"schema" : [{
"name": "BoolObject",
"properties": [{ "name": "boolCol", "type": "bool" }]
}],
"objects": [
{ "type": "BoolObject", "value": [false] },
{ "type": "BoolObject", "value": [true] },
{ "type": "BoolObject", "value": [true] }
],
"tests": [
["QueryCount", 2, "BoolObject", "boolCol == true"],
["QueryCount", 1, "BoolObject", "boolCol==false"],
["QueryCount", 1, "BoolObject", "boolCol != true"],
["QueryCount", 2, "BoolObject", "true == boolCol"],
["QueryCount", 2, "BoolObject", "boolCol == TRUE"],
["QueryCount", 1, "BoolObject", "boolCol == FALSE"],
["QueryCount", 2, "BoolObject", "boolCol == $0", true],
["QueryCount", 1, "BoolObject", "boolCol == $0", false],
["QueryCount", 0, "BoolObject", "boolCol == true && boolCol == false"],
["QueryCount", 3, "BoolObject", "boolCol == true || boolCol == false"],
["QueryThrows", "BoolObject", "boolCol == 0"],
["QueryThrows", "BoolObject", "boolCol == 1"],
["QueryThrows", "BoolObject", "boolCol == 'not a bool'"],
["QueryThrows", "BoolObject", "boolCol == $0", "not a bool"],
["QueryThrows", "BoolObject", "boolCol > true"],
["QueryThrows", "BoolObject", "boolCol >= true"],
["QueryThrows", "BoolObject", "boolCol < true"],
["QueryThrows", "BoolObject", "boolCol <= true"],
["QueryThrows", "BoolObject", "boolCol BEGINSWITH true"],
["QueryThrows", "BoolObject", "boolCol CONTAINS true"],
["QueryThrows", "BoolObject", "boolCol ENDSWITH true"]
]
},
"intTests" : {
"schema" : [{
"name": "IntObject",
"properties": [{ "name": "intCol", "type": "int" }]
}],
"objects": [
{ "type": "IntObject", "value": [-1] },
{ "type": "IntObject", "value": [0] },
{ "type": "IntObject", "value": [100] }
],
"tests": [
["QueryCount", 1, "IntObject", "intCol == -1"],
["QueryCount", 1, "IntObject", "intCol==0"],
["QueryCount", 0, "IntObject", "1 == intCol"],
["QueryCount", 2, "IntObject", "intCol != 0"],
["QueryCount", 2, "IntObject", "intCol > -1"],
["QueryCount", 3, "IntObject", "intCol >= -1"],
["QueryCount", 2, "IntObject", "intCol < 100"],
["QueryCount", 3, "IntObject", "intCol <= 100"],
["QueryCount", 1, "IntObject", "intCol > 0x1F"],
["QueryCount", 1, "IntObject", "intCol == $0", 100],
["QueryThrows", "IntObject", "intCol == 'not an int'"],
["QueryThrows", "IntObject", "intCol == true"],
["QueryThrows", "IntObject", "intCol == $0", "not an int"],
["QueryThrows", "IntObject", "intCol BEGINSWITH 1"],
["QueryThrows", "IntObject", "intCol CONTAINS 1"],
["QueryThrows", "IntObject", "intCol ENDSWITH 1"]
]
},
"floatTests" : {
"schema" : [{
"name": "FloatObject",
"properties": [{ "name": "floatCol", "type": "float" }]
}],
"objects": [
{ "type": "FloatObject", "value": [-1.001] },
{ "type": "FloatObject", "value": [0.0] },
{ "type": "FloatObject", "value": [100.2] }
],
"tests": [
["QueryCount", 1, "FloatObject", "floatCol == -1.001"],
["QueryCount", 1, "FloatObject", "floatCol = 0"],
["QueryCount", 0, "FloatObject", "1 == floatCol"],
["QueryCount", 2, "FloatObject", "floatCol != 0"],
["QueryCount", 2, "FloatObject", "floatCol > -1.001"],
["QueryCount", 3, "FloatObject", "floatCol >= -1.001"],
["QueryCount", 2, "FloatObject", "floatCol < 100.2"],
["QueryCount", 3, "FloatObject", "floatCol <= 100.2"],
["QueryCount", 1, "FloatObject", "floatCol > 0x1F"],
["QueryCount", 1, "FloatObject", "floatCol == $0", 100.2],
["QueryThrows", "FloatObject", "floatCol == 'not a float'"],
["QueryThrows", "FloatObject", "floatCol == true"],
["QueryThrows", "FloatObject", "floatCol == $0", "not a float"],
["QueryThrows", "FloatObject", "floatCol BEGINSWITH 1"],
["QueryThrows", "FloatObject", "floatCol CONTAINS 1"],
["QueryThrows", "FloatObject", "floatCol ENDSWITH 1"],
["Disabled", "QueryThrows", "FloatObject", "floatCol = 3.5e+38"],
["Disabled", "QueryThrows", "FloatObject", "floatCol = -3.5e+38"]
]
},
"doubleTests" : {
"schema" : [{
"name": "DoubleObject",
"properties": [{ "name": "doubleCol", "type": "double" }]
}],
"objects": [
{ "type": "DoubleObject", "value": [-1.001] },
{ "type": "DoubleObject", "value": [0.0] },
{ "type": "DoubleObject", "value": [100.2] }
],
"tests": [
["QueryCount", 1, "DoubleObject", "doubleCol == -1.001"],
["QueryCount", 1, "DoubleObject", "doubleCol == 0"],
["QueryCount", 0, "DoubleObject", "1 == doubleCol"],
["QueryCount", 2, "DoubleObject", "doubleCol != 0"],
["QueryCount", 2, "DoubleObject", "doubleCol > -1.001"],
["QueryCount", 3, "DoubleObject", "doubleCol >= -1.001"],
["QueryCount", 2, "DoubleObject", "doubleCol < 100.2"],
["QueryCount", 3, "DoubleObject", "doubleCol <= 100.2"],
["QueryCount", 1, "DoubleObject", "doubleCol > 0x1F"],
["QueryCount", 1, "DoubleObject", "doubleCol == $0", 100.2],
["QueryThrows", "DoubleObject", "doubleCol == 'not a double'"],
["QueryThrows", "DoubleObject", "doubleCol == true"],
["QueryThrows", "DoubleObject", "doubleCol == $0", "not a double"],
["QueryThrows", "DoubleObject", "doubleCol BEGINSWITH 1"],
["QueryThrows", "DoubleObject", "doubleCol CONTAINS 1"],
["QueryThrows", "DoubleObject", "doubleCol ENDSWITH 1"]
]
},
"stringTests" : {
"schema" : [{
"name": "StringObject",
"properties": [{ "name": "stringCol", "type": "string" }]
}],
"objects": [
{ "type": "StringObject", "value": ["A"] },
{ "type": "StringObject", "value": ["a"] },
{ "type": "StringObject", "value": ["a"] },
{ "type": "StringObject", "value": ["C"] },
{ "type": "StringObject", "value": ["c"] },
{ "type": "StringObject", "value": ["abc"] },
{ "type": "StringObject", "value": ["ABC"] },
{ "type": "StringObject", "value": [""] },
{ "type": "StringObject", "value": ["\\\"\\n\\0\\r\\\\'"] }
],
"tests": [
["QueryCount", 2, "StringObject", "stringCol == 'a'"],
["QueryCount", 1, "StringObject", "'c' == stringCol"],
["QueryCount", 2, "StringObject", "stringCol == \"a\""],
["QueryCount", 1, "StringObject", "stringCol=='abc'"],
["QueryCount", 1, "StringObject", "stringCol == ''"],
["QueryCount", 8, "StringObject", "stringCol != ''"],
["QueryCount", 1, "StringObject", "stringCol == \"\\\"\\n\\0\\r\\\\'\""],
["QueryCount", 3, "StringObject", "stringCol BEGINSWITH 'a'"],
["QueryCount", 1, "StringObject", "stringCol beginswith 'ab'"],
["QueryCount", 0, "StringObject", "stringCol BEGINSWITH 'abcd'"],
["QueryCount", 2, "StringObject", "stringCol BEGINSWITH 'A'"],
["QueryCount", 2, "StringObject", "stringCol ENDSWITH 'c'"],
["QueryCount", 1, "StringObject", "stringCol endswith 'bc'"],
["QueryCount", 9, "StringObject", "stringCol ENDSWITH ''"],
["QueryCount", 1, "StringObject", "stringCol CONTAINS 'b'"],
["QueryCount", 2, "StringObject", "stringCol contains 'c'"],
["QueryCount", 9, "StringObject", "stringCol CONTAINS ''"],
["QueryCount", 2, "StringObject", "stringCol == $0", "a"],
["QueryCount", 2, "StringObject", "stringCol ENDSWITH $0", "c"],
["QueryThrows", "StringObject", "stringCol == true"],
["QueryThrows", "StringObject", "stringCol == 123"],
["QueryThrows", "StringObject", "stringCol CONTAINS $0", 1],
["QueryCount", 3, "StringObject", "stringCol ==[c] 'a'"],
["QueryCount", 5, "StringObject", "stringCol BEGINSWITH[c] 'A'"],
["QueryCount", 4, "StringObject", "stringCol ENDSWITH[c] 'c'"],
["QueryCount", 2, "StringObject", "stringCol CONTAINS[c] 'B'"]
]
},
"binaryTests" : {
"schema" : [{
"name": "BinaryObject",
"properties": [{ "name": "binaryCol", "type": "data" }]
}],
"objects": [
{ "type": "BinaryObject", "value": [[1, 100, 233, 255, 0]] },
{ "type": "BinaryObject", "value": [[1, 100]] },
{ "type": "BinaryObject", "value": [[100]] },
{ "type": "BinaryObject", "value": [[]] },
{ "type": "BinaryObject", "value": [[255, 0]] }
],
"tests": [
["QueryCount", 1, "BinaryObject", "binaryCol == $0", [1, "binaryCol"]],
["QueryCount", 1, "BinaryObject", "$0 == binaryCol", [2, "binaryCol"]],
["QueryCount", 4, "BinaryObject", "binaryCol != $0", [0, "binaryCol"]],
["QueryCount", 1, "BinaryObject", "binaryCol BEGINSWITH $0", [0, "binaryCol"]],
["QueryCount", 2, "BinaryObject", "binaryCol BEGINSWITH $0", [1, "binaryCol"]],
["QueryCount", 2, "BinaryObject", "binaryCol ENDSWITH $0", [4, "binaryCol"]],
["QueryCount", 3, "BinaryObject", "binaryCol CONTAINS $0", [2, "binaryCol"]]
]
},
"objectTests" : {
"schema" : [
{ "name": "IntObject", "properties": [
{ "name": "intCol", "type": "int" }
]},
{ "name": "LinkObject", "properties": [
{ "name": "linkCol", "type": "object", "objectType": "IntObject" }
]}
],
"objects": [
{ "type": "LinkObject", "value": [[1]] },
{ "type": "LinkObject", "value": [[2]] },
{ "type": "LinkObject", "value": [null] }
],
"tests": [
["QueryCount", 1, "LinkObject", "linkCol == $0", [0, "linkCol"]],
["QueryCount", 1, "LinkObject", "$0 == linkCol", [1, "linkCol"]],
["QueryCount", 2, "LinkObject", "linkCol != $0", [0, "linkCol"]],
["QueryCount", 1, "LinkObject", "linkCol = null"],
["QueryCount", 2, "LinkObject", "linkCol != NULL"],
["QueryCount", 1, "LinkObject", "linkCol = $0", null],
["QueryThrows", "LinkObject", "linkCol > $0", [0, "linkCol"]],
["QueryThrows", "LinkObject", "intCol = $0", [0, "linkCol"]]
]
},
"compoundTests" : {
"schema" : [
{ "name": "IntObject",
"properties": [{ "name": "intCol", "type": "int" }],
"primaryKey" : "intCol" }
],
"objects": [
{ "type": "IntObject", "value": [0] },
{ "type": "IntObject", "value": [1] },
{ "type": "IntObject", "value": [2] },
{ "type": "IntObject", "value": [3] }
],
"tests": [
["ObjectSet", [], "IntObject", "intCol == 0 && intCol == 1"],
["ObjectSet", [0, 1], "IntObject", "intCol == 0 || intCol == 1"],
["ObjectSet", [0], "IntObject", "intCol == 0 && intCol != 1"],
["ObjectSet", [2, 3], "IntObject", "intCol >= 2 && intCol < 4"],
["ObjectSet", [0], "IntObject", "intCol == 0 && NOT intCol != 0"],
["ObjectSet", [0, 3], "IntObject", "intCol == 0 || NOT (intCol == 1 || intCol == 2)"],
["ObjectSet", [1], "IntObject", "(intCol == 0 || intCol == 1) && intCol >= 1"],
["ObjectSet", [1], "IntObject", "intCol >= 1 && (intCol == 0 || intCol == 1)"],
["ObjectSet", [0, 1], "IntObject", "intCol == 0 || (intCol == 1 && intCol >= 1)"],
["ObjectSet", [0, 1], "IntObject", "(intCol == 1 && intCol >= 1) || intCol == 0"],
["ObjectSet", [0, 1], "IntObject", "intCol == 0 || intCol == 1 && intCol >= 1"],
["ObjectSet", [0, 1, 2],"IntObject", "intCol == 0 || intCol == 1 || intCol <= 2"],
["ObjectSet", [0, 1], "IntObject", "intCol == 1 && intCol >= 1 || intCol == 0"],
["ObjectSet", [0, 1], "IntObject", "intCol == 1 || intCol == 0 && intCol <= 0 && intCol >= 0"],
["ObjectSet", [0, 1], "IntObject", "intCol == 0 || NOT (intCol == 3 && intCol >= 0) && intCol == 1"]
]
},
"keyPathTests" : {
"schema" : [
{
"name": "BasicTypesObject",
"properties": [
{ "name": "intCol", "type": "int" },
{ "name": "floatCol", "type": "float" },
{ "name": "doubleCol", "type": "double" },
{ "name": "stringCol", "type": "string" },
{ "name": "dateCol", "type": "date" },
{ "name": "dataCol", "type": "data" }
]
},
{
"name": "LinkTypesObject",
"primaryKey": "primaryKey",
"properties": [
{ "name": "primaryKey", "type": "int" },
{ "name": "basicLink", "type": "object", "objectType": "BasicTypesObject" },
{ "name": "linkLink", "type": "object", "objectType": "LinkTypesObject" }
]
}],
"objects": [
{ "type": "LinkTypesObject", "value": [0, [1, 0.1, 0.001, "1", 1, [1, 10, 100]], null] },
{ "type": "LinkTypesObject", "value": [1, null, [2, [1, 0.1, 0.001, "1", 1, [1, 10, 100]], null]] },
{ "type": "LinkTypesObject", "value": [3, null, [4, [2, 0.2, 0.002, "2", 2, [2, 20, 200]], null]] }
],
"tests": [
["ObjectSet", [0, 2], "LinkTypesObject", "basicLink.intCol == 1"],
["ObjectSet", [1], "LinkTypesObject", "linkLink.basicLink.intCol == 1"],
["ObjectSet", [1, 3], "LinkTypesObject", "linkLink.basicLink.intCol > 0"],
["ObjectSet", [0, 2], "LinkTypesObject", "basicLink.floatCol == 0.1"],
["ObjectSet", [1], "LinkTypesObject", "linkLink.basicLink.floatCol == 0.1"],
["ObjectSet", [1, 3], "LinkTypesObject", "linkLink.basicLink.floatCol > 0"]
]
},
"optionalTests" : {
"schema" : [
{
"name": "OptionalTypesObject",
"primaryKey": "primaryKey",
"properties": [
{ "name": "primaryKey", "type": "int" },
{ "name": "intCol", "type": "int", "optional": true },
{ "name": "floatCol", "type": "float", "optional": true },
{ "name": "doubleCol", "type": "double", "optional": true },
{ "name": "stringCol", "type": "string", "optional": true },
{ "name": "dateCol", "type": "date", "optional": true },
{ "name": "dataCol", "type": "data", "optional": true }
]
},
{
"name": "LinkTypesObject",
"primaryKey": "primaryKey",
"properties": [
{ "name": "primaryKey", "type": "int" },
{ "name": "basicLink", "type": "object", "objectType": "OptionalTypesObject" }
]
}],
"objects": [
{ "type": "LinkTypesObject", "value": [0, [0, 1, 0.1, 0.001, "1", 1, [1, 10, 100]]] },
{ "type": "LinkTypesObject", "value": [1, [1, null, null, null, null, null, null]] }
],
"tests": [
["ObjectSet", [1], "OptionalTypesObject", "intCol == null"],
["ObjectSet", [1], "OptionalTypesObject", "null == intCol"],
["ObjectSet", [0], "OptionalTypesObject", "intCol != null"],
["ObjectSet", [1], "OptionalTypesObject", "floatCol == null"],
["ObjectSet", [0], "OptionalTypesObject", "floatCol != null"],
["ObjectSet", [1], "OptionalTypesObject", "doubleCol == null"],
["ObjectSet", [0], "OptionalTypesObject", "doubleCol != null"],
["ObjectSet", [1], "OptionalTypesObject", "stringCol == null"],
["ObjectSet", [0], "OptionalTypesObject", "stringCol != null"],
["ObjectSet", [1], "OptionalTypesObject", "dateCol == null"],
["ObjectSet", [0], "OptionalTypesObject", "dateCol != null"],
["ObjectSet", [1], "OptionalTypesObject", "dataCol == null"],
["ObjectSet", [0], "OptionalTypesObject", "dataCol != null"],
["ObjectSet", [1], "LinkTypesObject", "basicLink.intCol == null"],
["ObjectSet", [0], "LinkTypesObject", "basicLink.intCol != null"],
["ObjectSet", [1], "LinkTypesObject", "basicLink.floatCol == null"],
["ObjectSet", [0], "LinkTypesObject", "basicLink.floatCol != null"],
["ObjectSet", [1], "LinkTypesObject", "basicLink.doubleCol == null"],
["ObjectSet", [0], "LinkTypesObject", "basicLink.doubleCol != null"],
["ObjectSet", [1], "LinkTypesObject", "basicLink.stringCol == null"],
["ObjectSet", [0], "LinkTypesObject", "basicLink.stringCol != null"],
["ObjectSet", [1], "LinkTypesObject", "basicLink.dateCol == null"],
["ObjectSet", [0], "LinkTypesObject", "basicLink.dateCol != null"],
["QueryThrows", "LinkTypesObject", "basicLink.dataCol == null"]
]
}
}

View File

@ -33,7 +33,7 @@ module.exports = {
testRealmConstructorPath: function() { testRealmConstructorPath: function() {
TestCase.assertThrows(function() { TestCase.assertThrows(function() {
new Realm('/invalidpath'); new Realm('');
}, 'Realm cannot be created with an invalid path'); }, 'Realm cannot be created with an invalid path');
TestCase.assertThrows(function() { TestCase.assertThrows(function() {
new Realm('test1.realm', 'invalidArgument'); new Realm('test1.realm', 'invalidArgument');

View File

@ -18,8 +18,6 @@
'use strict'; 'use strict';
var Realm = require('realm');
exports.TestObject = { exports.TestObject = {
name: 'TestObject', name: 'TestObject',
properties: { properties: {

331
tests/js/user-tests.js Normal file
View File

@ -0,0 +1,331 @@
////////////////////////////////////////////////////////////////////////////
//
// 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');
function uuid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
function assertIsUser(user, isAdmin) {
TestCase.assertType(user, 'object');
TestCase.assertType(user.token, 'string');
TestCase.assertType(user.identity, 'string');
TestCase.assertInstanceOf(user, Realm.Sync.User);
if (isAdmin !== undefined) {
TestCase.assertEqual(user.isAdmin, isAdmin);
}
}
function assertIsSameUser(value, user) {
assertIsUser(value);
TestCase.assertEqual(value.token, user.token);
TestCase.assertEqual(value.identity, user.identity);
TestCase.assertEqual(value.isAdmin, user.isAdmin);
}
function assertIsError(error, code) {
TestCase.assertInstanceOf(error, Error, 'The API should return an Error');
if (code) {
TestCase.assertEqual(error.code, code);
}
}
function assertIsAuthError(error, code, type) {
TestCase.assertInstanceOf(error, Realm.Sync.AuthError, 'The API should return an AuthError');
if (code) {
TestCase.assertEqual(error.code, code);
}
if (type) {
TestCase.assertEqual(error.type, type);
}
}
function failOnError(error) {
if (error) {
throw new Error(`Error ${error} was not expected`);
}
}
// Test the given requestFunc, passing it the given callback after it's been wrapped appropriately.
// This function makes sure that errors thrown in the async callback rejects the promise (making tests actually run).
function callbackTest(requestFunc, callback) {
return new Promise((resolve, reject) => {
function callbackWrapper() {
try {
callback.apply(this, Array.from(arguments));
resolve();
}
catch (e) {
reject(e);
}
}
requestFunc(callbackWrapper);
});
}
module.exports = {
testLogout() {
var username = uuid();
return callbackTest((callback) => Realm.Sync.User.register('http://localhost:9080', username, 'password', callback), (error, user) => {
failOnError(error);
assertIsUser(user);
assertIsSameUser(user, Realm.Sync.User.current);
user.logout();
// Is now logged out.
TestCase.assertUndefined(Realm.Sync.User.current);
// Can we open a realm with the registered user?
TestCase.assertThrows(function() {
var _realm = new Realm({sync: {user: user, url: 'realm://localhost:9080/~/test'}});
});
})
},
testRegisterUser() {
var username = uuid();
return callbackTest((callback) => Realm.Sync.User.register('http://localhost:9080', username, 'password', callback), (error, user) => {
failOnError(error);
assertIsUser(user);
// Can we open a realm with the registered user?
var realm = new Realm({sync: {user: user, url: 'realm://localhost:9080/~/test'}});
TestCase.assertInstanceOf(realm, Realm);
});
},
testRegisterExistingUser() {
var username = uuid();
return callbackTest((callback) => Realm.Sync.User.register('http://localhost:9080', username, 'password', callback), (error, user) => {
failOnError(error);
assertIsUser(user);
Realm.Sync.User.register('http://localhost:9080', username, 'password', (error, user) => {
assertIsAuthError(error, 613, 'https://realm.io/docs/object-server/problems/existing-account');
TestCase.assertUndefined(user);
});
});
},
testRegisterMissingUsername() {
return callbackTest((callback) => Realm.Sync.User.register('http://localhost:9080', undefined, 'password', callback), (error, user) => {
assertIsAuthError(error, 602, 'https://realm.io/docs/object-server/problems/missing-parameters');
TestCase.assertUndefined(user);
});
},
testRegisterMissingPassword() {
var username = uuid();
return callbackTest((callback) => Realm.Sync.User.register('http://localhost:9080', username, undefined, callback), (error, user) => {
assertIsAuthError(error, 602, 'https://realm.io/docs/object-server/problems/missing-parameters');
TestCase.assertUndefined(user);
});
},
testRegisterServerOffline() {
var username = uuid();
// Because it waits for answer this takes some time..
return callbackTest((callback) => Realm.Sync.User.register('http://fake_host.local', username, 'password', callback), (error, user) => {
assertIsError(error, 'ECONNRESET');
TestCase.assertUndefined(user);
});
},
testLogin() {
var username = uuid();
// Create user, logout the new user, then login
return callbackTest((callback) => Realm.Sync.User.register('http://localhost:9080', username, 'password', callback), (error, user) => {
failOnError(error);
user.logout();
Realm.Sync.User.login('http://localhost:9080', username, 'password', (error, user) => {
failOnError(error);
assertIsUser(user);
// Can we open a realm with the logged-in user?
var realm = new Realm({sync: {user: user, url: 'realm://localhost:9080/~/test'}});
TestCase.assertInstanceOf(realm, Realm);
realm.close();
});
});
},
testLoginMissingUsername() {
return callbackTest((callback) => Realm.Sync.User.login('http://localhost:9080', undefined, 'password', callback), (error, user) => {
assertIsAuthError(error, 602, 'https://realm.io/docs/object-server/problems/missing-parameters');
TestCase.assertUndefined(user);
});
},
testLoginMissingPassword() {
var username = uuid();
return callbackTest((callback) => Realm.Sync.User.login('http://localhost:9080', username, undefined, callback), (error, user) => {
assertIsAuthError(error, 602, 'https://realm.io/docs/object-server/problems/missing-parameters');
TestCase.assertUndefined(user);
});
},
testLoginNonExistingUser() {
return callbackTest((callback) => Realm.Sync.User.login('http://localhost:9080', 'does_not', 'exist', callback), (error, user) => {
assertIsAuthError(error, 612, 'https://realm.io/docs/object-server/problems/unknown-account');
TestCase.assertUndefined(user);
});
},
testLoginServerOffline() {
var username = uuid();
// Because it waits for answer this takes some time..
return callbackTest((callback) => Realm.Sync.User.register('http://fake_host.local', username, 'password', callback), (error, user) => {
assertIsError(error);
TestCase.assertUndefined(user);
});
},
testAll() {
return new Promise((resolve, _reject) => {
let all;
all = Realm.Sync.User.all;
TestCase.assertArrayLength(Object.keys(all), 0);
callbackTest((callback) => Realm.Sync.User.register('http://localhost:9080', uuid(), 'password', callback), (error, user1) => {
failOnError(error);
all = Realm.Sync.User.all;
TestCase.assertArrayLength(Object.keys(all), 1);
assertIsSameUser(all[user1.identity], user1);
Realm.Sync.User.register('http://localhost:9080', uuid(), 'password', (error, user2) => {
failOnError(error);
all = Realm.Sync.User.all;
TestCase.assertArrayLength(Object.keys(all), 2);
// NOTE: the list of users is in latest-first order.
assertIsSameUser(all[user2.identity], user2);
assertIsSameUser(all[user1.identity], user1);
user2.logout();
all = Realm.Sync.User.all;
TestCase.assertArrayLength(Object.keys(all), 1);
assertIsSameUser(all[user1.identity], user1);
user1.logout();
all = Realm.Sync.User.all;
TestCase.assertArrayLength(Object.keys(all), 0);
resolve();
});
});
});
},
testCurrent() {
return new Promise((resolve, _reject) => {
TestCase.assertUndefined(Realm.Sync.User.current);
callbackTest((callback) => Realm.Sync.User.register('http://localhost:9080', uuid(), 'password', callback), (error, user1) => {
failOnError(error);
assertIsSameUser(Realm.Sync.User.current, user1);
Realm.Sync.User.register('http://localhost:9080', uuid(), 'password', (error, user2) => {
failOnError(error);
TestCase.assertThrows(() => Realm.Sync.User.current, 'We expect Realm.Sync.User.current to throw if > 1 user.');
user2.logout();
assertIsSameUser(Realm.Sync.User.current, user1);
user1.logout();
TestCase.assertUndefined(Realm.Sync.User.current);
resolve();
});
});
});
},
testSynchronizeChangesWithTwoClientsAndOneUser() {
// Test Schema
class Foo {}
Foo.schema = {
name: 'Foo',
properties: {
string: 'string',
bars: { type: 'list', objectType: 'Bar' },
},
};
class Bar {}
Bar.schema = {
name: 'Bar',
properties: { integer: 'int' },
};
const schema = [Foo.schema, Bar.schema];
// Create a user, open two clients at different local paths, synchronize changes
const username = uuid();
return new Promise((resolve) => {
Realm.Sync.User.register('http://localhost:9080', username, 'password', (error ,user) => {
failOnError(error);
const clientA = new Realm({
path: 'testSynchronizeChangesWithTwoClientsAndOneUser_clientA.realm',
schema: schema,
sync: {
user: user,
url: 'http://localhost:9080/~/test',
},
});
const clientB = new Realm({
path: 'testSynchronizeChangesWithTwoClientsAndOneUser_clientB.realm',
schema: schema,
sync: {
user: user,
url: 'http://localhost:9080/~/test',
},
});
clientB.addListener('change', () => {
const foos = clientB.objects('Foo');
if (foos.length > 0) {
TestCase.assertEqual(foos.length, 1);
TestCase.assertEqual(foos[0].string, 'Hello, World!');
resolve();
}
});
clientA.write(() => {
clientA.create('Foo', { string: 'Hello, World!' });
});
});
});
},
};

View File

@ -21,17 +21,7 @@
'use strict'; 'use strict';
const Realm = require('../..'); const Realm = require('realm');
const handlers = {
create(options) {
let realm = new Realm(options.config);
realm.write(() => {
realm.create(options.type, options.properties);
});
}
};
process.on('message', (message) => { process.on('message', (message) => {
process.send(handleMessage(message)); process.send(handleMessage(message));
@ -39,14 +29,33 @@ process.on('message', (message) => {
function handleMessage(message) { function handleMessage(message) {
let error, result; let error, result;
if (message[0] == 'echo') {
return {result: message[1]}
}
try { try {
let handler = handlers[message.action]; let realm = new Realm(message[0]);
if (handler) { realm.write(() => {
result = handler(message); if (message[1] == 'create') {
} else { result = message[3].map((value) => realm.create(message[2], value));
throw new Error('Unknown worker action: ' + message.action);
} }
else if (message[1] == 'delete') {
let objects = realm.objects(message[2]);
objects = message[3].map((index) => objects[index]);
realm.delete(objects);
}
else if (message[1] == 'update') {
result = message[3].map((value) => realm.create(message[2], value, true));
}
else if (message[1] == 'list_method') {
var listObject = realm.objects(message[2])[0];
var list = listObject[message[3]];
result = list[message[4]].apply(list, message.slice(5));
}
else {
throw new Error('Unknown realm method: ' + message[1]);
}
});
} catch (e) { } catch (e) {
console.warn(e); console.warn(e);
error = e.message; error = e.message;

View File

@ -1,76 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// 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,
}
});
});
}
};

View File

@ -31,8 +31,10 @@ class Worker {
}); });
} }
postMessage(message) { postMessage(message) {
if (this._process) {
this._process.send(message); this._process.send(message);
} }
}
terminate() { terminate() {
if (this._process) { if (this._process) {
this._process.kill(); this._process.kill();

21
tests/package.json Normal file
View File

@ -0,0 +1,21 @@
{
"name": "realm-tests-jasmine",
"version": "0.0.1",
"private": true,
"dependencies": {
"es6-promise": "^3.2.1",
"jasmine": "^2.5.1",
"jasmine-console-reporter": "^1.2.7",
"jasmine-reporters": "^2.2.0",
"needle": "^1.3.0",
"terminate": "^1.0.8",
"tmp": "^0.0.30",
"url-parse": "^1.1.7"
},
"scripts": {
"test": "jasmine spec/unit_tests.js spec/sync_tests.js",
"test-nosync": "jasmine spec/unit_tests.js",
"test-sync-integration": "jasmine spec/sync_integration_tests.js",
"postinstall": "rm -f node_modules/realm && ln -s ../.. node_modules/realm"
}
}

View File

@ -73,6 +73,62 @@
remoteGlobalIDString = 13B07F861A680F5B00A75B9A; remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
remoteInfo = ReactTests; remoteInfo = ReactTests;
}; };
02022A7E1DA47F06000F0C4F /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F60690521CA2831E0003FB26 /* RealmReact.xcodeproj */;
proxyType = 1;
remoteGlobalIDString = F60690121CA2766F0003FB26;
remoteInfo = RealmReact;
};
02CBBBEF1DC2B3C00057A570 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 2D2A283A1D9B042B00D4039D;
remoteInfo = "RCTImage-tvOS";
};
02CBBBF31DC2B3C00057A570 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 2D2A28471D9B043800D4039D;
remoteInfo = "RCTLinking-tvOS";
};
02CBBBF71DC2B3C00057A570 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 2D2A28541D9B044C00D4039D;
remoteInfo = "RCTNetwork-tvOS";
};
02CBBBFB1DC2B3C00057A570 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 2D2A28611D9B046600D4039D;
remoteInfo = "RCTSettings-tvOS";
};
02CBBBFF1DC2B3C00057A570 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 2D2A287B1D9B048500D4039D;
remoteInfo = "RCTText-tvOS";
};
02CBBC041DC2B3C00057A570 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 2D2A28881D9B049200D4039D;
remoteInfo = "RCTWebSocket-tvOS";
};
02CBBC081DC2B3C00057A570 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 2D2A28131D9B038B00D4039D;
remoteInfo = "React-tvOS";
};
139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = { 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy; isa = PBXContainerItemProxy;
containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;
@ -210,6 +266,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
00C302C01ABCB91800DB3ED1 /* libRCTImage.a */, 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */,
02CBBBF01DC2B3C00057A570 /* libRCTImage-tvOS.a */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@ -218,6 +275,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */, 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */,
02CBBBF81DC2B3C00057A570 /* libRCTNetwork-tvOS.a */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@ -244,6 +302,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
139105C11AF99BAD00B5F7CC /* libRCTSettings.a */, 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */,
02CBBBFC1DC2B3C00057A570 /* libRCTSettings-tvOS.a */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@ -252,6 +311,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
139FDEF41B06529B00C62182 /* libRCTWebSocket.a */, 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */,
02CBBC051DC2B3C00057A570 /* libRCTWebSocket-tvOS.a */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@ -273,6 +333,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
146834041AC3E56700842450 /* libReact.a */, 146834041AC3E56700842450 /* libReact.a */,
02CBBC091DC2B3C00057A570 /* libReact-tvOS.a */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@ -281,6 +342,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
78C398B91ACF4ADC00677621 /* libRCTLinking.a */, 78C398B91ACF4ADC00677621 /* libRCTLinking.a */,
02CBBBF41DC2B3C00057A570 /* libRCTLinking-tvOS.a */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@ -309,6 +371,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
832341B51AAA6A8300B99B32 /* libRCTText.a */, 832341B51AAA6A8300B99B32 /* libRCTText.a */,
02CBBC001DC2B3C00057A570 /* libRCTText-tvOS.a */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@ -368,7 +431,6 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "ReactTestApp" */; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "ReactTestApp" */;
buildPhases = ( buildPhases = (
F65C4BCA1BC72C5A000A1793 /* Install Realm Node Modules */,
13B07F871A680F5B00A75B9A /* Sources */, 13B07F871A680F5B00A75B9A /* Sources */,
13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8C1A680F5B00A75B9A /* Frameworks */,
13B07F8E1A680F5B00A75B9A /* Resources */, 13B07F8E1A680F5B00A75B9A /* Resources */,
@ -378,6 +440,7 @@
buildRules = ( buildRules = (
); );
dependencies = ( dependencies = (
02022A7F1DA47F06000F0C4F /* PBXTargetDependency */,
); );
name = ReactTestApp; name = ReactTestApp;
productName = "Hello World"; productName = "Hello World";
@ -390,7 +453,7 @@
83CBB9F71A601CBA00E9B192 /* Project object */ = { 83CBB9F71A601CBA00E9B192 /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastUpgradeCheck = 0710; LastUpgradeCheck = 0800;
ORGANIZATIONNAME = Realm; ORGANIZATIONNAME = Realm;
TargetAttributes = { TargetAttributes = {
00E356ED1AD99517003FC87E = { 00E356ED1AD99517003FC87E = {
@ -500,6 +563,55 @@
remoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */; remoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR; sourceTree = BUILT_PRODUCTS_DIR;
}; };
02CBBBF01DC2B3C00057A570 /* libRCTImage-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libRCTImage-tvOS.a";
remoteRef = 02CBBBEF1DC2B3C00057A570 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
02CBBBF41DC2B3C00057A570 /* libRCTLinking-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libRCTLinking-tvOS.a";
remoteRef = 02CBBBF31DC2B3C00057A570 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
02CBBBF81DC2B3C00057A570 /* libRCTNetwork-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libRCTNetwork-tvOS.a";
remoteRef = 02CBBBF71DC2B3C00057A570 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
02CBBBFC1DC2B3C00057A570 /* libRCTSettings-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libRCTSettings-tvOS.a";
remoteRef = 02CBBBFB1DC2B3C00057A570 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
02CBBC001DC2B3C00057A570 /* libRCTText-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libRCTText-tvOS.a";
remoteRef = 02CBBBFF1DC2B3C00057A570 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
02CBBC051DC2B3C00057A570 /* libRCTWebSocket-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libRCTWebSocket-tvOS.a";
remoteRef = 02CBBC041DC2B3C00057A570 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
02CBBC091DC2B3C00057A570 /* libReact-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libReact-tvOS.a";
remoteRef = 02CBBC081DC2B3C00057A570 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
139105C11AF99BAD00B5F7CC /* libRCTSettings.a */ = { 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */ = {
isa = PBXReferenceProxy; isa = PBXReferenceProxy;
fileType = archive.ar; fileType = archive.ar;
@ -566,20 +678,6 @@
/* End PBXResourcesBuildPhase section */ /* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */
F65C4BCA1BC72C5A000A1793 /* Install Realm Node Modules */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Install Realm Node Modules";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "[ -s \"${HOME}/.nvm/nvm.sh\" ] && . \"${HOME}/.nvm/nvm.sh\" \nif [ -z \"$TEST_SCRIPT\" ]; then\n npm install realm realm-tests\nfi\ncp ../../../src/object-store/tests/query.json ../node_modules/realm-tests/query-tests.json\n";
};
F6EDE5BF1C49007200B1085F /* Bundle React Native code and images */ = { F6EDE5BF1C49007200B1085F /* Bundle React Native code and images */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
@ -623,6 +721,11 @@
target = 13B07F861A680F5B00A75B9A /* ReactTestApp */; target = 13B07F861A680F5B00A75B9A /* ReactTestApp */;
targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */; targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */;
}; };
02022A7F1DA47F06000F0C4F /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = RealmReact;
targetProxy = 02022A7E1DA47F06000F0C4F /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */ /* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */ /* Begin PBXVariantGroup section */
@ -704,6 +807,7 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
CC = "$(SRCROOT)/../../../scripts/ccache-clang.sh";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++"; CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
@ -713,16 +817,20 @@
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CXX = "$(SRCROOT)/../../../scripts/ccache-clang++.sh";
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES; ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO; GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0; GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = ( GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1", "DEBUG=1",
@ -741,9 +849,10 @@
"$(SRCROOT)/../node_modules/react-native/React/Base/**", "$(SRCROOT)/../node_modules/react-native/React/Base/**",
"$(SRCROOT)/../node_modules/react-native/React/Modules", "$(SRCROOT)/../node_modules/react-native/React/Modules",
); );
IPHONEOS_DEPLOYMENT_TARGET = 7.0; IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES; MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
OS_ACTIVITY_MODE = disable;
PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
}; };
@ -753,6 +862,7 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
CC = "$(SRCROOT)/../../../scripts/ccache-clang.sh";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++"; CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
@ -762,15 +872,19 @@
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES; COPY_PHASE_STRIP = YES;
CXX = "$(SRCROOT)/../../../scripts/ccache-clang++.sh";
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNDECLARED_SELECTOR = YES;
@ -783,8 +897,9 @@
"$(SRCROOT)/../node_modules/react-native/React/Base/**", "$(SRCROOT)/../node_modules/react-native/React/Base/**",
"$(SRCROOT)/../node_modules/react-native/React/Modules", "$(SRCROOT)/../node_modules/react-native/React/Modules",
); );
IPHONEOS_DEPLOYMENT_TARGET = 7.0; IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
OS_ACTIVITY_MODE = disable;
PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES; VALIDATE_PRODUCT = YES;

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0720" LastUpgradeVersion = "0800"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
@ -91,6 +91,13 @@
ReferencedContainer = "container:ReactTests.xcodeproj"> ReferencedContainer = "container:ReactTests.xcodeproj">
</BuildableReference> </BuildableReference>
</BuildableProductRunnable> </BuildableProductRunnable>
<EnvironmentVariables>
<EnvironmentVariable
key = "OS_ACTIVITY_MODE"
value = "disable"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
<AdditionalOptions> <AdditionalOptions>
</AdditionalOptions> </AdditionalOptions>
</LaunchAction> </LaunchAction>

View File

@ -6,11 +6,11 @@
"start": "react-native start" "start": "react-native start"
}, },
"dependencies": { "dependencies": {
"react": "~15.2.0", "react": "15.3.2",
"react-native": "^0.31.0", "react-native": "^0.37.0",
"react-native-fs": "^1.1.0", "react-native-fs": "^1.1.0",
"xmlbuilder": "^4.2.1",
"realm": "file:../..", "realm": "file:../..",
"realm-tests": "file:../js" "realm-tests": "file:../js",
"xmlbuilder": "^4.2.1"
} }
} }

View File

@ -0,0 +1,11 @@
'use strict';
var jasmineReporters = require('jasmine-reporters');
var junitReporter = new jasmineReporters.JUnitXmlReporter({
savePath: '.',
consolidateAll: false
});
jasmine.getEnv().addReporter(junitReporter);
var JasmineConsoleReporter = require('jasmine-console-reporter');
jasmine.getEnv().addReporter(new JasmineConsoleReporter());

Some files were not shown because too many files have changed in this diff Show More