2016-02-18 11:59:34 -08:00
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
//
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
2015-08-13 09:12:48 -07:00
|
|
|
|
2015-12-01 14:44:09 -08:00
|
|
|
#include "js_realm.hpp"
|
|
|
|
#include "js_object.hpp"
|
|
|
|
#include "js_results.hpp"
|
2016-03-28 13:21:36 -07:00
|
|
|
#include "jsc_list.hpp"
|
2015-12-01 14:44:09 -08:00
|
|
|
#include "js_schema.hpp"
|
|
|
|
#include "platform.hpp"
|
|
|
|
|
|
|
|
#include "shared_realm.hpp"
|
2016-03-03 14:45:44 -08:00
|
|
|
#include "impl/realm_coordinator.hpp"
|
2015-12-01 14:44:09 -08:00
|
|
|
#include "object_accessor.hpp"
|
|
|
|
#include "binding_context.hpp"
|
2016-03-28 13:21:36 -07:00
|
|
|
#include "results.hpp"
|
2015-12-01 14:44:09 -08:00
|
|
|
|
2015-12-02 03:42:47 +00:00
|
|
|
#include <cassert>
|
2015-08-13 09:12:48 -07:00
|
|
|
|
2016-03-29 16:17:57 -07:00
|
|
|
|
2015-08-13 09:12:48 -07:00
|
|
|
using namespace realm;
|
2016-02-26 11:08:59 -08:00
|
|
|
using RJSAccessor = realm::NativeAccessor<JSValueRef, JSContextRef>;
|
2015-08-13 09:12:48 -07:00
|
|
|
|
2016-01-12 03:01:06 +00:00
|
|
|
// static std::string s_defaultPath = realm::default_realm_file_directory() + "/default.realm";
|
|
|
|
static std::string s_defaultPath = "";
|
2015-08-13 09:12:48 -07:00
|
|
|
std::string RJSDefaultPath() {
|
2016-01-12 08:16:13 -08:00
|
|
|
if (s_defaultPath.size() == 0) {
|
|
|
|
s_defaultPath = realm::default_realm_file_directory() + "/default.realm";
|
|
|
|
}
|
2015-08-13 09:12:48 -07:00
|
|
|
return s_defaultPath;
|
|
|
|
}
|
|
|
|
void RJSSetDefaultPath(std::string path) {
|
|
|
|
s_defaultPath = path;
|
|
|
|
}
|
|
|
|
|
|
|
|
static JSValueRef GetDefaultPath(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException) {
|
|
|
|
return RJSValueForString(ctx, s_defaultPath);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool SetDefaultPath(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* jsException) {
|
|
|
|
try {
|
|
|
|
s_defaultPath = RJSValidatedStringForValue(ctx, value, "defaultPath");
|
|
|
|
}
|
|
|
|
catch (std::exception &ex) {
|
|
|
|
if (jsException) {
|
|
|
|
*jsException = RJSMakeError(ctx, ex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-03-17 15:49:07 -07:00
|
|
|
inline std::string RJSNormalizePath(std::string path) {
|
|
|
|
if (path.size() && path[0] != '/') {
|
|
|
|
return default_realm_file_directory() + "/" + path;
|
|
|
|
}
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
2015-08-13 09:12:48 -07:00
|
|
|
JSObjectRef RealmConstructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
|
|
|
|
try {
|
|
|
|
Realm::Config config;
|
2015-10-19 13:39:21 -07:00
|
|
|
std::map<std::string, realm::ObjectDefaults> defaults;
|
2016-02-18 11:09:51 -08:00
|
|
|
std::map<std::string, JSObjectRef> constructors;
|
2016-02-26 11:08:59 -08:00
|
|
|
if (argumentCount == 0) {
|
|
|
|
config.path = RJSDefaultPath();
|
|
|
|
}
|
|
|
|
else if (argumentCount == 1) {
|
|
|
|
JSValueRef value = arguments[0];
|
|
|
|
if (JSValueIsString(ctx, value)) {
|
|
|
|
config.path = RJSValidatedStringForValue(ctx, value, "path");
|
|
|
|
}
|
|
|
|
else if (JSValueIsObject(ctx, value)) {
|
|
|
|
JSObjectRef object = RJSValidatedValueToObject(ctx, value);
|
|
|
|
|
|
|
|
static JSStringRef pathString = JSStringCreateWithUTF8CString("path");
|
|
|
|
JSValueRef pathValue = RJSValidatedPropertyValue(ctx, object, pathString);
|
|
|
|
if (!JSValueIsUndefined(ctx, pathValue)) {
|
|
|
|
config.path = RJSValidatedStringForValue(ctx, pathValue, "path");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
config.path = RJSDefaultPath();
|
|
|
|
}
|
|
|
|
|
|
|
|
static JSStringRef schemaString = JSStringCreateWithUTF8CString("schema");
|
|
|
|
JSValueRef schemaValue = RJSValidatedPropertyValue(ctx, object, schemaString);
|
|
|
|
if (!JSValueIsUndefined(ctx, schemaValue)) {
|
|
|
|
config.schema.reset(new Schema(RJSParseSchema(ctx, RJSValidatedValueToObject(ctx, schemaValue), defaults, constructors)));
|
|
|
|
}
|
|
|
|
|
|
|
|
static JSStringRef schemaVersionString = JSStringCreateWithUTF8CString("schemaVersion");
|
|
|
|
JSValueRef versionValue = RJSValidatedPropertyValue(ctx, object, schemaVersionString);
|
|
|
|
if (JSValueIsNumber(ctx, versionValue)) {
|
|
|
|
config.schema_version = RJSValidatedValueToNumber(ctx, versionValue);
|
2015-08-13 09:12:48 -07:00
|
|
|
}
|
2016-02-26 11:08:59 -08:00
|
|
|
else {
|
|
|
|
config.schema_version = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static JSStringRef encryptionKeyString = JSStringCreateWithUTF8CString("encryptionKey");
|
|
|
|
JSValueRef encryptionKeyValue = RJSValidatedPropertyValue(ctx, object, encryptionKeyString);
|
|
|
|
if (!JSValueIsUndefined(ctx, encryptionKeyValue)) {
|
|
|
|
std::string encryptionKey = RJSAccessor::to_binary(ctx, encryptionKeyValue);
|
|
|
|
config.encryption_key = std::vector<char>(encryptionKey.begin(), encryptionKey.end());;
|
2015-08-13 09:12:48 -07:00
|
|
|
}
|
|
|
|
}
|
2016-02-26 11:08:59 -08:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
*jsException = RJSMakeError(ctx, "Invalid arguments when constructing 'Realm'");
|
|
|
|
return NULL;
|
2015-08-13 09:12:48 -07:00
|
|
|
}
|
2016-03-03 13:33:49 -08:00
|
|
|
|
2016-03-17 15:49:07 -07:00
|
|
|
config.path = RJSNormalizePath(config.path);
|
2016-03-03 13:33:49 -08:00
|
|
|
|
2015-11-23 22:05:06 -08:00
|
|
|
ensure_directory_exists_for_file(config.path);
|
2015-09-09 17:30:42 -07:00
|
|
|
SharedRealm realm = Realm::get_shared_realm(config);
|
2016-03-29 16:17:57 -07:00
|
|
|
auto delegate = new js::RealmDelegate<jsc::Types>(realm, JSContextGetGlobalContext(ctx));
|
2015-11-13 18:20:40 -08:00
|
|
|
if (!realm->m_binding_context) {
|
2016-03-29 16:17:57 -07:00
|
|
|
realm->m_binding_context.reset(delegate);
|
2015-09-09 17:30:42 -07:00
|
|
|
}
|
2016-03-29 16:17:57 -07:00
|
|
|
delegate->m_defaults = defaults;
|
|
|
|
delegate->m_constructors = constructors;
|
|
|
|
return js::WrapObject(ctx, RJSRealmClass(), new SharedRealm(realm));
|
2015-08-13 09:12:48 -07:00
|
|
|
}
|
|
|
|
catch (std::exception &ex) {
|
|
|
|
if (jsException) {
|
|
|
|
*jsException = RJSMakeError(ctx, ex);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-26 12:11:35 -08:00
|
|
|
bool RealmHasInstance(JSContextRef ctx, JSObjectRef constructor, JSValueRef value, JSValueRef* exception) {
|
|
|
|
return JSValueIsObjectOfClass(ctx, value, RJSRealmClass());
|
|
|
|
}
|
|
|
|
|
|
|
|
static const JSStaticValue RealmStaticProperties[] = {
|
|
|
|
{"defaultPath", GetDefaultPath, SetDefaultPath, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
2016-03-29 13:36:01 -07:00
|
|
|
template<typename ContextType, typename ObjectType, typename ValueType, typename ReturnType, typename ExceptionType>
|
|
|
|
void RealmSchemaVersion(ContextType ctx, ObjectType thisObject, size_t argumentCount, const ValueType arguments[], ReturnType &returnObject, ExceptionType &exceptionObject) {
|
2016-03-17 15:49:07 -07:00
|
|
|
try {
|
2016-03-18 10:04:35 -07:00
|
|
|
RJSValidateArgumentRange(argumentCount, 1, 2);
|
2016-03-17 15:49:07 -07:00
|
|
|
|
|
|
|
Realm::Config config;
|
|
|
|
config.path = RJSNormalizePath(RJSValidatedStringForValue(ctx, arguments[0]));
|
2016-03-18 10:04:35 -07:00
|
|
|
if (argumentCount == 2) {
|
2016-03-29 13:36:01 -07:00
|
|
|
auto encryptionKeyValue = arguments[1];
|
2016-03-18 10:04:35 -07:00
|
|
|
std::string encryptionKey = RJSAccessor::to_binary(ctx, encryptionKeyValue);
|
|
|
|
config.encryption_key = std::vector<char>(encryptionKey.begin(), encryptionKey.end());
|
|
|
|
}
|
|
|
|
|
2016-03-18 09:51:04 -07:00
|
|
|
auto version = Realm::get_schema_version(config);
|
|
|
|
if (version == ObjectStore::NotVersioned) {
|
2016-03-29 13:36:01 -07:00
|
|
|
RJSSetReturnNumber(ctx, returnObject, -1);
|
2016-03-18 09:51:04 -07:00
|
|
|
}
|
|
|
|
else {
|
2016-03-29 13:36:01 -07:00
|
|
|
RJSSetReturnNumber(ctx, returnObject, version);
|
2016-03-18 09:51:04 -07:00
|
|
|
}
|
2016-03-17 15:49:07 -07:00
|
|
|
}
|
|
|
|
catch (std::exception &exp) {
|
2016-03-29 13:36:01 -07:00
|
|
|
RJSSetException(ctx, exceptionObject, exp);
|
2016-03-17 15:49:07 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-29 13:36:01 -07:00
|
|
|
WRAP_METHOD(RealmSchemaVersion)
|
|
|
|
|
2016-03-17 15:49:07 -07:00
|
|
|
static const JSStaticFunction RealmConstructorFuncs[] = {
|
|
|
|
{"schemaVersion", RealmSchemaVersion, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
|
|
|
|
{NULL, NULL},
|
|
|
|
};
|
|
|
|
|
2015-08-13 09:12:48 -07:00
|
|
|
JSClassRef RJSRealmConstructorClass() {
|
|
|
|
JSClassDefinition realmConstructorDefinition = kJSClassDefinitionEmpty;
|
2016-02-26 12:11:35 -08:00
|
|
|
realmConstructorDefinition.attributes = kJSClassAttributeNoAutomaticPrototype;
|
|
|
|
realmConstructorDefinition.className = "RealmConstructor";
|
2015-08-13 09:12:48 -07:00
|
|
|
realmConstructorDefinition.callAsConstructor = RealmConstructor;
|
2016-02-26 12:11:35 -08:00
|
|
|
realmConstructorDefinition.hasInstance = RealmHasInstance;
|
|
|
|
realmConstructorDefinition.staticValues = RealmStaticProperties;
|
2016-03-17 15:49:07 -07:00
|
|
|
realmConstructorDefinition.staticFunctions = RealmConstructorFuncs;
|
2015-08-13 09:12:48 -07:00
|
|
|
return JSClassCreate(&realmConstructorDefinition);
|
|
|
|
}
|
|
|
|
|
|
|
|
JSValueRef RealmGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) {
|
|
|
|
static JSStringRef s_pathString = JSStringCreateWithUTF8CString("path");
|
|
|
|
if (JSStringIsEqual(propertyName, s_pathString)) {
|
|
|
|
return RJSValueForString(ctx, RJSGetInternal<SharedRealm *>(object)->get()->config().path);
|
|
|
|
}
|
|
|
|
|
|
|
|
static JSStringRef s_schemaVersion = JSStringCreateWithUTF8CString("schemaVersion");
|
|
|
|
if (JSStringIsEqual(propertyName, s_schemaVersion)) {
|
|
|
|
return JSValueMakeNumber(ctx, RJSGetInternal<SharedRealm *>(object)->get()->config().schema_version);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-03-03 02:49:37 -08:00
|
|
|
std::string RJSValidatedObjectTypeForValue(SharedRealm &realm, JSContextRef ctx, JSValueRef value) {
|
2016-02-24 17:34:20 -08:00
|
|
|
if (JSValueIsObject(ctx, value) && JSObjectIsConstructor(ctx, (JSObjectRef)value)) {
|
|
|
|
JSObjectRef constructor = (JSObjectRef)value;
|
|
|
|
|
2016-03-29 16:17:57 -07:00
|
|
|
auto delegate = js::get_delegate<jsc::Types>(realm.get());
|
|
|
|
for (auto pair : delegate->m_constructors) {
|
2016-02-24 17:34:20 -08:00
|
|
|
if (pair.second == constructor) {
|
|
|
|
return pair.first;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
throw std::runtime_error("Constructor was not registered in the schema for this Realm");
|
|
|
|
}
|
|
|
|
|
|
|
|
return RJSValidatedStringForValue(ctx, value, "objectType");
|
|
|
|
}
|
|
|
|
|
2016-03-29 13:36:01 -07:00
|
|
|
template<typename ContextType, typename ObjectType, typename ValueType, typename ReturnType, typename ExceptionType>
|
|
|
|
void RealmObjects(ContextType ctx, ObjectType thisObject, size_t argumentCount, const ValueType arguments[], ReturnType &returnObject, ExceptionType &exceptionObject) { try {
|
2016-02-24 17:34:20 -08:00
|
|
|
RJSValidateArgumentCount(argumentCount, 1);
|
|
|
|
|
2015-08-13 09:12:48 -07:00
|
|
|
SharedRealm sharedRealm = *RJSGetInternal<SharedRealm *>(thisObject);
|
2016-03-03 02:49:37 -08:00
|
|
|
std::string className = RJSValidatedObjectTypeForValue(sharedRealm, ctx, arguments[0]);
|
2016-03-28 13:21:36 -07:00
|
|
|
returnObject = RJSResultsCreate(ctx, sharedRealm, className);
|
2015-08-13 09:12:48 -07:00
|
|
|
}
|
|
|
|
catch (std::exception &exp) {
|
2016-03-28 13:21:36 -07:00
|
|
|
RJSSetException(ctx, exceptionObject, exp);
|
2015-08-13 09:12:48 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-29 13:36:01 -07:00
|
|
|
template<typename ContextType, typename ObjectType, typename ValueType, typename ReturnType, typename ExceptionType>
|
|
|
|
void RealmCreateObject(ContextType ctx, ObjectType thisObject, size_t argumentCount, const ValueType arguments[], ReturnType &returnObject, ExceptionType &exceptionObject) {
|
|
|
|
try {
|
2015-08-13 09:12:48 -07:00
|
|
|
RJSValidateArgumentRange(argumentCount, 2, 3);
|
|
|
|
|
|
|
|
SharedRealm sharedRealm = *RJSGetInternal<SharedRealm *>(thisObject);
|
2016-03-03 02:49:37 -08:00
|
|
|
std::string className = RJSValidatedObjectTypeForValue(sharedRealm, ctx, arguments[0]);
|
2016-02-24 17:34:20 -08:00
|
|
|
auto &schema = sharedRealm->config().schema;
|
|
|
|
auto object_schema = schema->find(className);
|
|
|
|
|
|
|
|
if (object_schema == schema->end()) {
|
2016-03-28 13:21:36 -07:00
|
|
|
throw std::runtime_error("Object type '" + className + "' not found in schema.");
|
2015-09-01 15:47:06 -07:00
|
|
|
}
|
2015-08-13 09:12:48 -07:00
|
|
|
|
2016-03-29 13:36:01 -07:00
|
|
|
auto object = RJSValidatedValueToObject(ctx, arguments[1]);
|
2015-08-14 09:47:33 -07:00
|
|
|
if (RJSIsValueArray(ctx, arguments[1])) {
|
2015-09-09 17:16:32 -07:00
|
|
|
object = RJSDictForPropertyArray(ctx, *object_schema, object);
|
2015-08-14 09:47:33 -07:00
|
|
|
}
|
|
|
|
|
2015-09-03 14:05:56 -07:00
|
|
|
bool update = false;
|
|
|
|
if (argumentCount == 3) {
|
2016-03-28 13:21:36 -07:00
|
|
|
update = RJSValidatedValueToBoolean(ctx, arguments[2]);
|
2015-09-03 14:05:56 -07:00
|
|
|
}
|
|
|
|
|
2016-03-29 13:36:01 -07:00
|
|
|
returnObject = RJSObjectCreate(ctx, Object::create<ValueType>(ctx, sharedRealm, *object_schema, object, update));
|
2015-08-14 09:47:33 -07:00
|
|
|
}
|
|
|
|
catch (std::exception &exp) {
|
2016-03-28 13:21:36 -07:00
|
|
|
RJSSetException(ctx, exceptionObject, exp);
|
2015-08-14 09:47:33 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-29 13:36:01 -07:00
|
|
|
template<typename ContextType, typename ObjectType, typename ValueType, typename ReturnType, typename ExceptionType>
|
|
|
|
void RealmDelete(ContextType ctx, ObjectType thisObject, size_t argumentCount, const ValueType arguments[], ReturnType &returnObject, ExceptionType &exceptionObject) { try {
|
2015-08-14 09:47:33 -07:00
|
|
|
RJSValidateArgumentCount(argumentCount, 1);
|
2016-03-28 13:21:36 -07:00
|
|
|
|
|
|
|
SharedRealm realm = *RJSGetInternal<SharedRealm *>(thisObject);
|
|
|
|
if (!realm->is_in_transaction()) {
|
|
|
|
throw std::runtime_error("Can only delete objects within a transaction.");
|
|
|
|
}
|
|
|
|
|
2016-03-29 13:36:01 -07:00
|
|
|
auto arg = RJSValidatedValueToObject(ctx, arguments[0]);
|
2016-03-28 13:21:36 -07:00
|
|
|
if (RJSValueIsObjectOfClass(ctx, arg, RJSObjectClass())) {
|
|
|
|
Object *object = RJSGetInternal<Object *>(arg);
|
|
|
|
realm::TableRef table = ObjectStore::table_for_object_type(realm->read_group(), object->get_object_schema().name);
|
|
|
|
table->move_last_over(object->row().get_index());
|
|
|
|
}
|
|
|
|
else if (RJSIsValueArray(ctx, arg)) {
|
|
|
|
size_t length = RJSValidatedListLength(ctx, arg);
|
2015-09-02 21:31:29 -07:00
|
|
|
for (long i = length-1; i >= 0; i--) {
|
2016-03-28 13:21:36 -07:00
|
|
|
JSObjectRef jsObject = RJSValidatedValueToObject(ctx, RJSValidatedObjectAtIndex(ctx, arg, (unsigned int)i));
|
2016-03-29 13:36:01 -07:00
|
|
|
if (!RJSValueIsObjectOfClass(ctx, jsObject, RJSObjectClass())) {
|
2016-03-28 13:21:36 -07:00
|
|
|
throw std::runtime_error("Argument to 'delete' must be a Realm object or a collection of Realm objects.");
|
2015-09-02 21:31:29 -07:00
|
|
|
}
|
2016-03-28 13:21:36 -07:00
|
|
|
|
|
|
|
Object *object = RJSGetInternal<Object *>(jsObject);
|
|
|
|
realm::TableRef table = ObjectStore::table_for_object_type(realm->read_group(), object->get_object_schema().name);
|
|
|
|
table->move_last_over(object->row().get_index());
|
2015-08-14 09:47:33 -07:00
|
|
|
}
|
2015-08-13 09:12:48 -07:00
|
|
|
}
|
2016-03-28 13:21:36 -07:00
|
|
|
else if(RJSValueIsObjectOfClass(ctx, arg, RJSResultsClass())) {
|
|
|
|
Results *results = RJSGetInternal<Results *>(arg);
|
|
|
|
results->clear();
|
2015-08-13 09:12:48 -07:00
|
|
|
}
|
2016-03-28 13:21:36 -07:00
|
|
|
else if(RJSValueIsObjectOfClass(ctx, arg, RJSListClass())) {
|
|
|
|
List *list = RJSGetInternal<List *>(arg);
|
|
|
|
list->delete_all();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
throw std::runtime_error("Argument to 'delete' must be a Realm object or a collection of Realm objects.");
|
2015-08-14 09:47:33 -07:00
|
|
|
}
|
2015-08-13 09:12:48 -07:00
|
|
|
}
|
|
|
|
catch (std::exception &exp) {
|
2016-03-28 13:21:36 -07:00
|
|
|
RJSSetException(ctx, exceptionObject, exp);
|
2015-08-13 09:12:48 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-29 13:36:01 -07:00
|
|
|
template<typename ContextType, typename ObjectType, typename ValueType, typename ReturnType, typename ExceptionType>
|
|
|
|
void RealmDeleteAll(ContextType ctx, ObjectType thisObject, size_t argumentCount, const ValueType arguments[], ReturnType &returnObject, ExceptionType &exceptionObject) { try {
|
2015-09-08 14:07:14 -07:00
|
|
|
RJSValidateArgumentCount(argumentCount, 0);
|
|
|
|
|
|
|
|
SharedRealm realm = *RJSGetInternal<SharedRealm *>(thisObject);
|
|
|
|
|
|
|
|
if (!realm->is_in_transaction()) {
|
|
|
|
throw std::runtime_error("Can only delete objects within a transaction.");
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto objectSchema : *realm->config().schema) {
|
2015-09-09 17:16:32 -07:00
|
|
|
ObjectStore::table_for_object_type(realm->read_group(), objectSchema.name)->clear();
|
2015-09-08 14:07:14 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (std::exception &exp) {
|
2016-03-28 13:21:36 -07:00
|
|
|
RJSSetException(ctx, exceptionObject, exp);
|
2015-09-08 14:07:14 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-29 13:36:01 -07:00
|
|
|
template<typename ContextType, typename ObjectType, typename ValueType, typename ReturnType, typename ExceptionType>
|
|
|
|
void RealmWrite(ContextType ctx, ObjectType thisObject, size_t argumentCount, const ValueType arguments[], ReturnType &returnObject, ExceptionType &exceptionObject) {
|
2016-03-28 13:21:36 -07:00
|
|
|
SharedRealm realm = *RJSGetInternal<SharedRealm *>(thisObject);
|
2015-08-13 09:12:48 -07:00
|
|
|
try {
|
|
|
|
RJSValidateArgumentCount(argumentCount, 1);
|
|
|
|
|
2016-03-29 13:36:01 -07:00
|
|
|
auto object = RJSValidatedValueToFunction(ctx, arguments[0]);
|
2015-08-14 09:47:33 -07:00
|
|
|
realm->begin_transaction();
|
2016-03-28 13:21:36 -07:00
|
|
|
RJSCallFunction(ctx, object, thisObject, 0, NULL);
|
|
|
|
realm->commit_transaction();
|
2015-08-13 09:12:48 -07:00
|
|
|
}
|
|
|
|
catch (std::exception &exp) {
|
2016-03-28 13:21:36 -07:00
|
|
|
if (realm->is_in_transaction()) {
|
|
|
|
realm->cancel_transaction();
|
2015-08-13 09:12:48 -07:00
|
|
|
}
|
2016-03-28 13:21:36 -07:00
|
|
|
RJSSetException(ctx, exceptionObject, exp);
|
2015-08-13 09:12:48 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-26 19:18:24 -07:00
|
|
|
std::string RJSValidatedNotificationName(JSContextRef ctx, JSValueRef value) {
|
|
|
|
std::string name = RJSValidatedStringForValue(ctx, value);
|
|
|
|
if (name != "change") {
|
|
|
|
throw std::runtime_error("Only the 'change' notification name is supported.");
|
|
|
|
}
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
2016-03-29 13:36:01 -07:00
|
|
|
template<typename ContextType, typename ObjectType, typename ValueType, typename ReturnType, typename ExceptionType>
|
|
|
|
void RealmAddListener(ContextType ctx, ObjectType thisObject, size_t argumentCount, const ValueType arguments[], ReturnType &returnObject, ExceptionType &exceptionObject) { try {
|
2015-10-26 19:18:24 -07:00
|
|
|
RJSValidateArgumentCount(argumentCount, 2);
|
|
|
|
__unused std::string name = RJSValidatedNotificationName(ctx, arguments[0]);
|
2016-03-29 13:36:01 -07:00
|
|
|
auto callback = RJSValidatedValueToFunction(ctx, arguments[1]);
|
2015-08-13 09:12:48 -07:00
|
|
|
|
|
|
|
SharedRealm realm = *RJSGetInternal<SharedRealm *>(thisObject);
|
2016-03-29 16:17:57 -07:00
|
|
|
static_cast<js::RealmDelegate<jsc::Types> *>(realm->m_binding_context.get())->add_notification(callback);
|
2015-08-13 09:12:48 -07:00
|
|
|
}
|
|
|
|
catch (std::exception &exp) {
|
2016-03-28 13:21:36 -07:00
|
|
|
RJSSetException(ctx, exceptionObject, exp);
|
2015-08-13 09:12:48 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-29 13:36:01 -07:00
|
|
|
template<typename ContextType, typename ObjectType, typename ValueType, typename ReturnType, typename ExceptionType>
|
|
|
|
void RealmRemoveListener(ContextType ctx, ObjectType thisObject, size_t argumentCount, const ValueType arguments[], ReturnType &returnObject, ExceptionType &exceptionObject) { try {
|
2015-10-26 19:18:24 -07:00
|
|
|
RJSValidateArgumentCount(argumentCount, 2);
|
|
|
|
__unused std::string name = RJSValidatedNotificationName(ctx, arguments[0]);
|
2016-03-29 13:36:01 -07:00
|
|
|
auto callback = RJSValidatedValueToFunction(ctx, arguments[1]);
|
2015-10-26 16:15:46 -07:00
|
|
|
|
|
|
|
SharedRealm realm = *RJSGetInternal<SharedRealm *>(thisObject);
|
2016-03-29 16:17:57 -07:00
|
|
|
static_cast<js::RealmDelegate<jsc::Types> *>(realm->m_binding_context.get())->remove_notification(callback);
|
2015-10-26 16:15:46 -07:00
|
|
|
}
|
|
|
|
catch (std::exception &exp) {
|
2016-03-28 13:21:36 -07:00
|
|
|
RJSSetException(ctx, exceptionObject, exp);
|
2015-10-26 16:15:46 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-29 13:36:01 -07:00
|
|
|
template<typename ContextType, typename ObjectType, typename ValueType, typename ReturnType, typename ExceptionType>
|
|
|
|
void RealmRemoveAllListeners(ContextType ctx, ObjectType thisObject, size_t argumentCount, const ValueType arguments[], ReturnType &returnObject, ExceptionType &exceptionObject) { try {
|
2015-10-26 19:18:24 -07:00
|
|
|
RJSValidateArgumentRange(argumentCount, 0, 1);
|
|
|
|
if (argumentCount) {
|
|
|
|
RJSValidatedNotificationName(ctx, arguments[0]);
|
|
|
|
}
|
|
|
|
|
2015-10-26 16:15:46 -07:00
|
|
|
SharedRealm realm = *RJSGetInternal<SharedRealm *>(thisObject);
|
2016-03-29 16:17:57 -07:00
|
|
|
static_cast<js::RealmDelegate<jsc::Types> *>(realm->m_binding_context.get())->remove_all_notifications();
|
2015-10-26 16:15:46 -07:00
|
|
|
}
|
|
|
|
catch (std::exception &exp) {
|
2016-03-28 13:21:36 -07:00
|
|
|
RJSSetException(ctx, exceptionObject, exp);
|
2015-10-26 16:15:46 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-29 13:36:01 -07:00
|
|
|
template<typename ContextType, typename ObjectType, typename ValueType, typename ReturnType, typename ExceptionType>
|
|
|
|
void RealmClose(ContextType ctx, ObjectType thisObject, size_t argumentCount, const ValueType arguments[], ReturnType &returnObject, ExceptionType &exceptionObject) { try {
|
2015-10-12 17:01:51 -07:00
|
|
|
RJSValidateArgumentCount(argumentCount, 0);
|
|
|
|
SharedRealm realm = *RJSGetInternal<SharedRealm *>(thisObject);
|
2015-10-19 14:25:35 -07:00
|
|
|
realm->close();
|
2015-10-12 17:01:51 -07:00
|
|
|
}
|
|
|
|
catch (std::exception &exp) {
|
2016-03-28 13:21:36 -07:00
|
|
|
RJSSetException(ctx, exceptionObject, exp);
|
2015-10-12 17:01:51 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-28 13:21:36 -07:00
|
|
|
WRAP_METHOD(RealmObjects)
|
|
|
|
WRAP_METHOD(RealmCreateObject)
|
|
|
|
WRAP_METHOD(RealmDelete)
|
|
|
|
WRAP_METHOD(RealmDeleteAll)
|
|
|
|
WRAP_METHOD(RealmWrite)
|
|
|
|
WRAP_METHOD(RealmAddListener)
|
|
|
|
WRAP_METHOD(RealmRemoveListener)
|
|
|
|
WRAP_METHOD(RealmRemoveAllListeners)
|
|
|
|
WRAP_METHOD(RealmClose)
|
|
|
|
|
2015-10-19 15:52:32 -07:00
|
|
|
static const JSStaticFunction RJSRealmFuncs[] = {
|
2015-10-08 10:43:38 -06:00
|
|
|
{"objects", RealmObjects, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
|
|
|
|
{"create", RealmCreateObject, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
|
|
|
|
{"delete", RealmDelete, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
|
|
|
|
{"deleteAll", RealmDeleteAll, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
|
|
|
|
{"write", RealmWrite, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
|
2015-10-26 16:15:46 -07:00
|
|
|
{"addListener", RealmAddListener, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
|
|
|
|
{"removeListener", RealmRemoveListener, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
|
|
|
|
{"removeAllListeners", RealmRemoveAllListeners, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
|
2015-10-12 17:01:51 -07:00
|
|
|
{"close", RealmClose, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
|
2015-10-08 10:43:38 -06:00
|
|
|
{NULL, NULL},
|
|
|
|
};
|
2015-08-13 09:12:48 -07:00
|
|
|
|
|
|
|
JSClassRef RJSRealmClass() {
|
2015-10-08 10:43:38 -06:00
|
|
|
static JSClassRef s_realmClass = RJSCreateWrapperClass<SharedRealm *>("Realm", RealmGetProperty, NULL, RJSRealmFuncs);
|
2015-08-13 09:12:48 -07:00
|
|
|
return s_realmClass;
|
|
|
|
}
|
2016-03-29 16:17:57 -07:00
|
|
|
|
|
|
|
|
|
|
|
namespace realm {
|
|
|
|
namespace js {
|
|
|
|
JSClassRef RealmClass() { return RJSRealmClass(); };
|
|
|
|
}
|
|
|
|
}
|