convert more of Realm
This commit is contained in:
parent
9626842f8e
commit
b4990fbbff
|
@ -125,6 +125,7 @@
|
|||
02A3C7A41BC4341500B1A7BE /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; };
|
||||
02AFE5871CA9B23400953DA3 /* jsc_list.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = jsc_list.cpp; path = jsc/jsc_list.cpp; sourceTree = "<group>"; };
|
||||
02AFE5881CA9B23400953DA3 /* jsc_list.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = jsc_list.hpp; path = jsc/jsc_list.hpp; sourceTree = "<group>"; };
|
||||
02AFE5B11CAB133500953DA3 /* js_compat.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = js_compat.hpp; path = jsc/js_compat.hpp; sourceTree = "<group>"; };
|
||||
02B58CB11AE99CEC009B348C /* RealmJS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RealmJS.framework; 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; };
|
||||
|
@ -259,6 +260,7 @@
|
|||
0290480C1C0428DF00ABDED4 /* js_schema.hpp */,
|
||||
0290480D1C0428DF00ABDED4 /* js_util.cpp */,
|
||||
0290480E1C0428DF00ABDED4 /* js_util.hpp */,
|
||||
02AFE5B11CAB133500953DA3 /* js_compat.hpp */,
|
||||
02AFE5871CA9B23400953DA3 /* jsc_list.cpp */,
|
||||
02AFE5881CA9B23400953DA3 /* jsc_list.hpp */,
|
||||
029048351C042A3C00ABDED4 /* platform.hpp */,
|
||||
|
|
|
@ -1,68 +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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "types.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace realm {
|
||||
namespace js {
|
||||
|
||||
void *GetInternal(Types::ObjectType jsObject) {
|
||||
return JSObjectGetPrivate(jsObject);
|
||||
}
|
||||
|
||||
|
||||
std::string StringForStringType(Types::StringType jsString);
|
||||
std::string StringForValueType(Types::ContextType ctx, Types::ValueType value);
|
||||
std::string ValidatedStringForValueType(Types::ContextType ctx, Types::ValueType value, const char * name = nullptr);
|
||||
bool ValidatedBooleanForValueType(Types::ContextType ctx, Types::ValueType value, const char * name = nullptr);
|
||||
|
||||
Types::StringType StringTypeForString(const std::string &str);
|
||||
Types::ValueType ValueTypeForString(Types::ContextType ctx, const std::string &str);
|
||||
|
||||
bool IsValueTypeArray(Types::ContextType ctx, Types::ValueType value);
|
||||
bool IsValueTypeArrayBuffer(Types::ContextType ctx, Types::ValueType value);
|
||||
bool IsValueTypeDate(Types::ContextType ctx, Types::ValueType value);
|
||||
|
||||
Types::ObjectType ValidatedValueTypeToObject(Types::ContextType ctx, Types::ValueType value, const char *message = NULL);
|
||||
Types::ObjectType ValidatedValueTypeToDate(Types::ContextType ctx, Types::ValueType value, const char *message = NULL);
|
||||
Types::ObjectType ValidatedValueTypeToFunction(Types::ContextType ctx, Types::ValueType value, const char *message = NULL);
|
||||
double ValidatedValueTypeToNumber(Types::ContextType ctx, Types::ValueType value);
|
||||
Types::ValueType ValidatedPropertyValue(Types::ContextType ctx, Types::ObjectType object, Types::StringType property);
|
||||
Types::ValueType ValidatedPropertyAtIndex(Types::ContextType ctx, Types::ObjectType object, unsigned int index);
|
||||
Types::ObjectType ValidatedObjectProperty(Types::ContextType ctx, Types::ObjectType object, Types::StringType property, const char *err = NULL);
|
||||
Types::ObjectType ValidatedObjectAtIndex(Types::ContextType ctx, Types::ObjectType object, unsigned int index);
|
||||
std::string ValidatedStringProperty(Types::ContextType ctx, Types::ObjectType object, Types::StringType property);
|
||||
bool ValidatedBooleanProperty(Types::ContextType ctx, Types::ObjectType object, Types::StringType property, const char *err = NULL);
|
||||
size_t ValidatedListLength(Types::ContextType ctx, Types::ObjectType object);
|
||||
void ValidatedSetProperty(Types::ContextType ctx, Types::ObjectType object, Types::StringType propertyName, Types::ValueType value, JSPropertyAttributes attributes = 0);
|
||||
|
||||
bool IsValueTypeIsObject(Types::ContextType ctx, Types::ValueType value);
|
||||
bool IsValueTypeObjectOfType(Types::ContextType ctx, Types::ValueType value, Types::StringType type);
|
||||
bool ObjectTypeHasProperty(Types::ContextType ctx, Types::ObjectType object, Types::StringType propName);
|
||||
|
||||
template<typename T>
|
||||
void SetReturnNumber(Types::ContextType ctx, Types::ValueType &returnObject, T number);
|
||||
void SetReturnArray(Types::ContextType ctx, size_t count, const Types::ValueType *objects, Types::ValueType &returnObject);\
|
||||
void SetReturnUndefined(Types::ContextType ctx, Types::ValueType &returnObject);
|
||||
|
||||
void SetException(Types::ContextType ctx, Types::ValueType * &exceptionObject, std::exception &exception);
|
||||
|
||||
}}
|
|
@ -35,8 +35,8 @@
|
|||
using RJSAccessor = realm::NativeAccessor<JSValueRef, JSContextRef>;
|
||||
using namespace realm;
|
||||
|
||||
template<typename ContextType, typename ThisType, typename ArgumentsType, typename ReturnType, typename ExceptionType>
|
||||
void ListPush(ContextType ctx, ThisType thisObject, size_t argumentCount, const ArgumentsType &arguments, ReturnType &returnObject, ExceptionType &exceptionObject) {
|
||||
template<typename ContextType, typename ObjectType, typename ValueType, typename ReturnType, typename ExceptionType>
|
||||
void ListPush(ContextType ctx, ObjectType thisObject, size_t argumentCount, const ValueType arguments[], ReturnType &returnObject, ExceptionType &exceptionObject) {
|
||||
try {
|
||||
List *list = RJSGetInternal<List *>(thisObject);
|
||||
RJSValidateArgumentCountIsAtLeast(argumentCount, 1);
|
||||
|
@ -50,8 +50,8 @@ void ListPush(ContextType ctx, ThisType thisObject, size_t argumentCount, const
|
|||
}
|
||||
}
|
||||
|
||||
template<typename ContextType, typename ThisType, typename ArgumentsType, typename ReturnType, typename ExceptionType>
|
||||
void ListPop(ContextType ctx, ThisType thisObject, size_t argumentCount, const ArgumentsType &arguments, ReturnType &returnObject, ExceptionType &exceptionObject) {
|
||||
template<typename ContextType, typename ObjectType, typename ValueType, typename ReturnType, typename ExceptionType>
|
||||
void ListPop(ContextType ctx, ObjectType thisObject, size_t argumentCount, const ValueType arguments[], ReturnType &returnObject, ExceptionType &exceptionObject) {
|
||||
try {
|
||||
List *list = RJSGetInternal<List *>(thisObject);
|
||||
RJSValidateArgumentCount(argumentCount, 0);
|
||||
|
@ -73,8 +73,8 @@ void ListPop(ContextType ctx, ThisType thisObject, size_t argumentCount, const A
|
|||
}
|
||||
|
||||
|
||||
template<typename ContextType, typename ThisType, typename ArgumentsType, typename ReturnType, typename ExceptionType>
|
||||
void ListUnshift(ContextType ctx, ThisType thisObject, size_t argumentCount, const ArgumentsType &arguments, ReturnType &returnObject, ExceptionType &exceptionObject) {
|
||||
template<typename ContextType, typename ObjectType, typename ValueType, typename ReturnType, typename ExceptionType>
|
||||
void ListUnshift(ContextType ctx, ObjectType thisObject, size_t argumentCount, const ValueType arguments[], ReturnType &returnObject, ExceptionType &exceptionObject) {
|
||||
try {
|
||||
List *list = RJSGetInternal<List *>(thisObject);
|
||||
RJSValidateArgumentCountIsAtLeast(argumentCount, 1);
|
||||
|
@ -88,8 +88,8 @@ void ListUnshift(ContextType ctx, ThisType thisObject, size_t argumentCount, con
|
|||
}
|
||||
}
|
||||
|
||||
template<typename ContextType, typename ThisType, typename ArgumentsType, typename ReturnType, typename ExceptionType>
|
||||
void ListShift(ContextType ctx, ThisType thisObject, size_t argumentCount, const ArgumentsType &arguments, ReturnType &returnObject, ExceptionType &exceptionObject) {
|
||||
template<typename ContextType, typename ObjectType, typename ValueType, typename ReturnType, typename ExceptionType>
|
||||
void ListShift(ContextType ctx, ObjectType thisObject, size_t argumentCount, const ValueType arguments[], ReturnType &returnObject, ExceptionType &exceptionObject) {
|
||||
try {
|
||||
List *list = RJSGetInternal<List *>(thisObject);
|
||||
RJSValidateArgumentCount(argumentCount, 0);
|
||||
|
@ -107,8 +107,8 @@ void ListShift(ContextType ctx, ThisType thisObject, size_t argumentCount, const
|
|||
}
|
||||
}
|
||||
|
||||
template<typename ContextType, typename ThisType, typename ArgumentsType, typename ReturnType, typename ExceptionType>
|
||||
void ListSplice(ContextType ctx, ThisType thisObject, size_t argumentCount, const ArgumentsType &arguments, ReturnType &returnObject, ExceptionType &exceptionObject) {
|
||||
template<typename ContextType, typename ObjectType, typename ValueType, typename ReturnType, typename ExceptionType>
|
||||
void ListSplice(ContextType ctx, ObjectType thisObject, size_t argumentCount, const ValueType arguments[], ReturnType &returnObject, ExceptionType &exceptionObject) {
|
||||
try {
|
||||
List *list = RJSGetInternal<List *>(thisObject);
|
||||
size_t size = list->size();
|
||||
|
@ -144,8 +144,8 @@ void ListSplice(ContextType ctx, ThisType thisObject, size_t argumentCount, cons
|
|||
}
|
||||
|
||||
|
||||
template<typename ContextType, typename ThisType, typename ArgumentsType, typename ReturnType, typename ExceptionType>
|
||||
void ListStaticResults(ContextType ctx, ThisType thisObject, size_t argumentCount, const ArgumentsType &arguments, ReturnType &returnObject, ExceptionType &exceptionObject) {
|
||||
template<typename ContextType, typename ObjectType, typename ValueType, typename ReturnType, typename ExceptionType>
|
||||
void ListStaticResults(ContextType ctx, ObjectType thisObject, size_t argumentCount, const ValueType arguments[], ReturnType &returnObject, ExceptionType &exceptionObject) {
|
||||
try {
|
||||
List *list = RJSGetInternal<List *>(thisObject);
|
||||
RJSValidateArgumentCount(argumentCount, 0);
|
||||
|
@ -156,8 +156,8 @@ void ListStaticResults(ContextType ctx, ThisType thisObject, size_t argumentCoun
|
|||
}
|
||||
}
|
||||
|
||||
template<typename ContextType, typename ThisType, typename ArgumentsType, typename ReturnType, typename ExceptionType>
|
||||
void ListFiltered(ContextType ctx, ThisType thisObject, size_t argumentCount, const ArgumentsType &arguments, ReturnType &returnObject, ExceptionType &exceptionObject) {
|
||||
template<typename ContextType, typename ObjectType, typename ValueType, typename ReturnType, typename ExceptionType>
|
||||
void ListFiltered(ContextType ctx, ObjectType thisObject, size_t argumentCount, const ValueType arguments[], ReturnType &returnObject, ExceptionType &exceptionObject) {
|
||||
try {
|
||||
List *list = RJSGetInternal<List *>(thisObject);
|
||||
RJSValidateArgumentCountIsAtLeast(argumentCount, 1);
|
||||
|
@ -170,8 +170,8 @@ void ListFiltered(ContextType ctx, ThisType thisObject, size_t argumentCount, co
|
|||
}
|
||||
}
|
||||
|
||||
template<typename ContextType, typename ThisType, typename ArgumentsType, typename ReturnType, typename ExceptionType>
|
||||
void ListSorted(ContextType ctx, ThisType thisObject, size_t argumentCount, const ArgumentsType &arguments, ReturnType &returnObject, ExceptionType &exceptionObject) {
|
||||
template<typename ContextType, typename ObjectType, typename ValueType, typename ReturnType, typename ExceptionType>
|
||||
void ListSorted(ContextType ctx, ObjectType thisObject, size_t argumentCount, const ValueType arguments[], ReturnType &returnObject, ExceptionType &exceptionObject) {
|
||||
try {
|
||||
List *list = RJSGetInternal<List *>(thisObject);
|
||||
RJSValidateArgumentRange(argumentCount, 1, 2);
|
||||
|
|
|
@ -238,34 +238,34 @@ static const JSStaticValue RealmStaticProperties[] = {
|
|||
{NULL, NULL}
|
||||
};
|
||||
|
||||
JSValueRef RealmSchemaVersion(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
|
||||
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) {
|
||||
try {
|
||||
RJSValidateArgumentRange(argumentCount, 1, 2);
|
||||
|
||||
Realm::Config config;
|
||||
config.path = RJSNormalizePath(RJSValidatedStringForValue(ctx, arguments[0]));
|
||||
if (argumentCount == 2) {
|
||||
JSValueRef encryptionKeyValue = arguments[1];
|
||||
auto encryptionKeyValue = arguments[1];
|
||||
std::string encryptionKey = RJSAccessor::to_binary(ctx, encryptionKeyValue);
|
||||
config.encryption_key = std::vector<char>(encryptionKey.begin(), encryptionKey.end());
|
||||
}
|
||||
|
||||
auto version = Realm::get_schema_version(config);
|
||||
if (version == ObjectStore::NotVersioned) {
|
||||
return JSValueMakeNumber(ctx, -1);
|
||||
RJSSetReturnNumber(ctx, returnObject, -1);
|
||||
}
|
||||
else {
|
||||
return JSValueMakeNumber(ctx, version);
|
||||
RJSSetReturnNumber(ctx, returnObject, version);
|
||||
}
|
||||
}
|
||||
catch (std::exception &exp) {
|
||||
if (jsException) {
|
||||
*jsException = RJSMakeError(ctx, exp);
|
||||
}
|
||||
RJSSetException(ctx, exceptionObject, exp);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
WRAP_METHOD(RealmSchemaVersion)
|
||||
|
||||
static const JSStaticFunction RealmConstructorFuncs[] = {
|
||||
{"schemaVersion", RealmSchemaVersion, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
|
||||
{NULL, NULL},
|
||||
|
@ -311,8 +311,8 @@ std::string RJSValidatedObjectTypeForValue(SharedRealm &realm, JSContextRef ctx,
|
|||
return RJSValidatedStringForValue(ctx, value, "objectType");
|
||||
}
|
||||
|
||||
template<typename ContextType, typename ThisType, typename ArgumentsType, typename ReturnType, typename ExceptionType>
|
||||
void RealmObjects(ContextType ctx, ThisType thisObject, size_t argumentCount, const ArgumentsType &arguments, ReturnType &returnObject, ExceptionType &exceptionObject) { try {
|
||||
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 {
|
||||
RJSValidateArgumentCount(argumentCount, 1);
|
||||
|
||||
SharedRealm sharedRealm = *RJSGetInternal<SharedRealm *>(thisObject);
|
||||
|
@ -324,8 +324,9 @@ void RealmObjects(ContextType ctx, ThisType thisObject, size_t argumentCount, co
|
|||
}
|
||||
}
|
||||
|
||||
template<typename ContextType, typename ThisType, typename ArgumentsType, typename ReturnType, typename ExceptionType>
|
||||
void RealmCreateObject(ContextType ctx, ThisType thisObject, size_t argumentCount, const ArgumentsType &arguments, ReturnType &returnObject, ExceptionType &exceptionObject) { try {
|
||||
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 {
|
||||
RJSValidateArgumentRange(argumentCount, 2, 3);
|
||||
|
||||
SharedRealm sharedRealm = *RJSGetInternal<SharedRealm *>(thisObject);
|
||||
|
@ -337,7 +338,7 @@ void RealmCreateObject(ContextType ctx, ThisType thisObject, size_t argumentCoun
|
|||
throw std::runtime_error("Object type '" + className + "' not found in schema.");
|
||||
}
|
||||
|
||||
JSObjectRef object = RJSValidatedValueToObject(ctx, arguments[1]);
|
||||
auto object = RJSValidatedValueToObject(ctx, arguments[1]);
|
||||
if (RJSIsValueArray(ctx, arguments[1])) {
|
||||
object = RJSDictForPropertyArray(ctx, *object_schema, object);
|
||||
}
|
||||
|
@ -347,15 +348,15 @@ void RealmCreateObject(ContextType ctx, ThisType thisObject, size_t argumentCoun
|
|||
update = RJSValidatedValueToBoolean(ctx, arguments[2]);
|
||||
}
|
||||
|
||||
returnObject = RJSObjectCreate(ctx, Object::create<JSValueRef>(ctx, sharedRealm, *object_schema, object, update));
|
||||
returnObject = RJSObjectCreate(ctx, Object::create<ValueType>(ctx, sharedRealm, *object_schema, object, update));
|
||||
}
|
||||
catch (std::exception &exp) {
|
||||
RJSSetException(ctx, exceptionObject, exp);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ContextType, typename ThisType, typename ArgumentsType, typename ReturnType, typename ExceptionType>
|
||||
void RealmDelete(ContextType ctx, ThisType thisObject, size_t argumentCount, const ArgumentsType &arguments, ReturnType &returnObject, ExceptionType &exceptionObject) { try {
|
||||
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 {
|
||||
RJSValidateArgumentCount(argumentCount, 1);
|
||||
|
||||
SharedRealm realm = *RJSGetInternal<SharedRealm *>(thisObject);
|
||||
|
@ -363,7 +364,7 @@ void RealmDelete(ContextType ctx, ThisType thisObject, size_t argumentCount, con
|
|||
throw std::runtime_error("Can only delete objects within a transaction.");
|
||||
}
|
||||
|
||||
JSObjectRef arg = RJSValidatedValueToObject(ctx, arguments[0]);
|
||||
auto arg = RJSValidatedValueToObject(ctx, arguments[0]);
|
||||
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);
|
||||
|
@ -373,7 +374,7 @@ void RealmDelete(ContextType ctx, ThisType thisObject, size_t argumentCount, con
|
|||
size_t length = RJSValidatedListLength(ctx, arg);
|
||||
for (long i = length-1; i >= 0; i--) {
|
||||
JSObjectRef jsObject = RJSValidatedValueToObject(ctx, RJSValidatedObjectAtIndex(ctx, arg, (unsigned int)i));
|
||||
if (!JSValueIsObjectOfClass(ctx, jsObject, RJSObjectClass())) {
|
||||
if (!RJSValueIsObjectOfClass(ctx, jsObject, RJSObjectClass())) {
|
||||
throw std::runtime_error("Argument to 'delete' must be a Realm object or a collection of Realm objects.");
|
||||
}
|
||||
|
||||
|
@ -399,8 +400,8 @@ void RealmDelete(ContextType ctx, ThisType thisObject, size_t argumentCount, con
|
|||
}
|
||||
}
|
||||
|
||||
template<typename ContextType, typename ThisType, typename ArgumentsType, typename ReturnType, typename ExceptionType>
|
||||
void RealmDeleteAll(ContextType ctx, ThisType thisObject, size_t argumentCount, const ArgumentsType &arguments, ReturnType &returnObject, ExceptionType &exceptionObject) { try {
|
||||
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 {
|
||||
RJSValidateArgumentCount(argumentCount, 0);
|
||||
|
||||
SharedRealm realm = *RJSGetInternal<SharedRealm *>(thisObject);
|
||||
|
@ -418,13 +419,13 @@ void RealmDeleteAll(ContextType ctx, ThisType thisObject, size_t argumentCount,
|
|||
}
|
||||
}
|
||||
|
||||
template<typename ContextType, typename ThisType, typename ArgumentsType, typename ReturnType, typename ExceptionType>
|
||||
void RealmWrite(ContextType ctx, ThisType thisObject, size_t argumentCount, const ArgumentsType &arguments, ReturnType &returnObject, ExceptionType &exceptionObject) {
|
||||
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) {
|
||||
SharedRealm realm = *RJSGetInternal<SharedRealm *>(thisObject);
|
||||
try {
|
||||
RJSValidateArgumentCount(argumentCount, 1);
|
||||
|
||||
JSObjectRef object = RJSValidatedValueToFunction(ctx, arguments[0]);
|
||||
auto object = RJSValidatedValueToFunction(ctx, arguments[0]);
|
||||
realm->begin_transaction();
|
||||
RJSCallFunction(ctx, object, thisObject, 0, NULL);
|
||||
realm->commit_transaction();
|
||||
|
@ -445,11 +446,11 @@ std::string RJSValidatedNotificationName(JSContextRef ctx, JSValueRef value) {
|
|||
return name;
|
||||
}
|
||||
|
||||
template<typename ContextType, typename ThisType, typename ArgumentsType, typename ReturnType, typename ExceptionType>
|
||||
void RealmAddListener(ContextType ctx, ThisType thisObject, size_t argumentCount, const ArgumentsType &arguments, ReturnType &returnObject, ExceptionType &exceptionObject) { try {
|
||||
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 {
|
||||
RJSValidateArgumentCount(argumentCount, 2);
|
||||
__unused std::string name = RJSValidatedNotificationName(ctx, arguments[0]);
|
||||
JSObjectRef callback = RJSValidatedValueToFunction(ctx, arguments[1]);
|
||||
auto callback = RJSValidatedValueToFunction(ctx, arguments[1]);
|
||||
|
||||
SharedRealm realm = *RJSGetInternal<SharedRealm *>(thisObject);
|
||||
static_cast<RJSRealmDelegate *>(realm->m_binding_context.get())->add_notification(callback);
|
||||
|
@ -459,11 +460,11 @@ void RealmAddListener(ContextType ctx, ThisType thisObject, size_t argumentCount
|
|||
}
|
||||
}
|
||||
|
||||
template<typename ContextType, typename ThisType, typename ArgumentsType, typename ReturnType, typename ExceptionType>
|
||||
void RealmRemoveListener(ContextType ctx, ThisType thisObject, size_t argumentCount, const ArgumentsType &arguments, ReturnType &returnObject, ExceptionType &exceptionObject) { try {
|
||||
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 {
|
||||
RJSValidateArgumentCount(argumentCount, 2);
|
||||
__unused std::string name = RJSValidatedNotificationName(ctx, arguments[0]);
|
||||
JSObjectRef callback = RJSValidatedValueToFunction(ctx, arguments[1]);
|
||||
auto callback = RJSValidatedValueToFunction(ctx, arguments[1]);
|
||||
|
||||
SharedRealm realm = *RJSGetInternal<SharedRealm *>(thisObject);
|
||||
static_cast<RJSRealmDelegate *>(realm->m_binding_context.get())->remove_notification(callback);
|
||||
|
@ -473,8 +474,8 @@ void RealmRemoveListener(ContextType ctx, ThisType thisObject, size_t argumentCo
|
|||
}
|
||||
}
|
||||
|
||||
template<typename ContextType, typename ThisType, typename ArgumentsType, typename ReturnType, typename ExceptionType>
|
||||
void RealmRemoveAllListeners(ContextType ctx, ThisType thisObject, size_t argumentCount, const ArgumentsType &arguments, ReturnType &returnObject, ExceptionType &exceptionObject) { try {
|
||||
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 {
|
||||
RJSValidateArgumentRange(argumentCount, 0, 1);
|
||||
if (argumentCount) {
|
||||
RJSValidatedNotificationName(ctx, arguments[0]);
|
||||
|
@ -488,8 +489,8 @@ void RealmRemoveAllListeners(ContextType ctx, ThisType thisObject, size_t argume
|
|||
}
|
||||
}
|
||||
|
||||
template<typename ContextType, typename ThisType, typename ArgumentsType, typename ReturnType, typename ExceptionType>
|
||||
void RealmClose(ContextType ctx, ThisType thisObject, size_t argumentCount, const ArgumentsType &arguments, ReturnType &returnObject, ExceptionType &exceptionObject) { try {
|
||||
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 {
|
||||
RJSValidateArgumentCount(argumentCount, 0);
|
||||
SharedRealm realm = *RJSGetInternal<SharedRealm *>(thisObject);
|
||||
realm->close();
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#include <stdexcept>
|
||||
#include <cmath>
|
||||
#include "property.hpp"
|
||||
|
||||
#include "js_compat.hpp"
|
||||
#include "schema.hpp"
|
||||
|
||||
#define WRAP_METHOD(METHOD_NAME) \
|
||||
|
@ -38,7 +40,6 @@ JSValueRef METHOD_NAME(JSContextRef ctx, JSObjectRef function, JSObjectRef thisO
|
|||
return returnObject; \
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline void RJSFinalize(JSObjectRef object) {
|
||||
delete static_cast<T>(JSObjectGetPrivate(object));
|
||||
|
@ -314,3 +315,4 @@ static void RJSCallFunction(JSContextRef ctx, JSObjectRef function, JSObjectRef
|
|||
static bool RJSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsClass) {
|
||||
return JSValueIsObjectOfClass(ctx, value, jsClass);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "types.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace realm {
|
||||
namespace js {
|
||||
|
||||
static bool ValueIsUndefined(Types::Context ctx, Types::Value value) { return JSValueIsUndefined(ctx, value); }
|
||||
static bool ValueIsNull(Types::Context ctx, Types::Value value) { return JSValueIsNull(ctx, value); }
|
||||
static bool ValueIsBoolean(Types::Context ctx, Types::Value value) { return JSValueIsBoolean(ctx, value); }
|
||||
static bool ValueIsNumber(Types::Context ctx, Types::Value value) { return JSValueIsNumber(ctx, value); }
|
||||
static bool ValueIsString(Types::Context ctx, Types::Value value) { return JSValueIsString(ctx, value); }
|
||||
static bool ValueIsObject(Types::Context ctx, Types::Value value) { return JSValueIsObject(ctx, value); }
|
||||
|
||||
}}
|
|
@ -0,0 +1,572 @@
|
|||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "js_realm.hpp"
|
||||
#include "js_object.hpp"
|
||||
#include "js_results.hpp"
|
||||
#include "jsc_list.hpp"
|
||||
#include "js_schema.hpp"
|
||||
#include "platform.hpp"
|
||||
|
||||
#include "shared_realm.hpp"
|
||||
#include "impl/realm_coordinator.hpp"
|
||||
#include "object_accessor.hpp"
|
||||
#include "binding_context.hpp"
|
||||
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
|
||||
using namespace realm;
|
||||
using RJSAccessor = realm::NativeAccessor<JSValueRef, JSContextRef>;
|
||||
|
||||
class RJSRealmDelegate : public BindingContext {
|
||||
public:
|
||||
virtual void changes_available() {
|
||||
assert(0);
|
||||
}
|
||||
virtual void did_change(std::vector<ObserverState> const& observers, std::vector<void*> const& invalidated) {
|
||||
notify("change");
|
||||
}
|
||||
virtual std::vector<ObserverState> get_observed_rows() {
|
||||
return std::vector<ObserverState>();
|
||||
}
|
||||
virtual void will_change(std::vector<ObserverState> const& observers,
|
||||
std::vector<void*> const& invalidated) {}
|
||||
|
||||
RJSRealmDelegate(WeakRealm realm, JSGlobalContextRef ctx) : m_context(ctx), m_realm(realm) {
|
||||
JSGlobalContextRetain(m_context);
|
||||
}
|
||||
|
||||
~RJSRealmDelegate() {
|
||||
remove_all_notifications();
|
||||
|
||||
for (auto constructor : m_constructors) {
|
||||
JSValueUnprotect(m_context, constructor.second);
|
||||
}
|
||||
for (auto objectDefaults : m_defaults) {
|
||||
for (auto value : objectDefaults.second) {
|
||||
JSValueUnprotect(m_context, value.second);
|
||||
}
|
||||
}
|
||||
JSGlobalContextRelease(m_context);
|
||||
}
|
||||
|
||||
void add_notification(JSObjectRef notification) {
|
||||
if (!m_notifications.count(notification)) {
|
||||
JSValueProtect(m_context, notification);
|
||||
m_notifications.insert(notification);
|
||||
}
|
||||
}
|
||||
void remove_notification(JSObjectRef notification) {
|
||||
if (m_notifications.count(notification)) {
|
||||
JSValueUnprotect(m_context, notification);
|
||||
m_notifications.erase(notification);
|
||||
}
|
||||
}
|
||||
void remove_all_notifications() {
|
||||
for (auto notification : m_notifications) {
|
||||
JSValueUnprotect(m_context, notification);
|
||||
}
|
||||
m_notifications.clear();
|
||||
}
|
||||
|
||||
std::map<std::string, ObjectDefaults> m_defaults;
|
||||
std::map<std::string, JSObjectRef> m_constructors;
|
||||
|
||||
private:
|
||||
std::set<JSObjectRef> m_notifications;
|
||||
JSGlobalContextRef m_context;
|
||||
WeakRealm m_realm;
|
||||
|
||||
void notify(const char *notification_name) {
|
||||
JSValueRef arguments[2];
|
||||
SharedRealm realm = m_realm.lock();
|
||||
if (!realm) {
|
||||
throw std::runtime_error("Realm no longer exists");
|
||||
}
|
||||
JSObjectRef realm_object = RJSWrapObject<SharedRealm *>(m_context, RJSRealmClass(), new SharedRealm(realm));
|
||||
arguments[0] = realm_object;
|
||||
arguments[1] = RJSValueForString(m_context, notification_name);
|
||||
|
||||
for (auto callback : m_notifications) {
|
||||
JSValueRef ex = NULL;
|
||||
JSObjectCallAsFunction(m_context, callback, realm_object, 2, arguments, &ex);
|
||||
if (ex) {
|
||||
throw RJSException(m_context, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::map<std::string, ObjectDefaults> &RJSDefaults(Realm *realm) {
|
||||
return static_cast<RJSRealmDelegate *>(realm->m_binding_context.get())->m_defaults;
|
||||
}
|
||||
|
||||
std::map<std::string, JSObjectRef> &RJSConstructors(Realm *realm) {
|
||||
return static_cast<RJSRealmDelegate *>(realm->m_binding_context.get())->m_constructors;
|
||||
}
|
||||
|
||||
// static std::string s_defaultPath = realm::default_realm_file_directory() + "/default.realm";
|
||||
static std::string s_defaultPath = "";
|
||||
std::string RJSDefaultPath() {
|
||||
if (s_defaultPath.size() == 0) {
|
||||
s_defaultPath = realm::default_realm_file_directory() + "/default.realm";
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
inline std::string RJSNormalizePath(std::string path) {
|
||||
if (path.size() && path[0] != '/') {
|
||||
return default_realm_file_directory() + "/" + path;
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
JSObjectRef RealmConstructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
|
||||
try {
|
||||
Realm::Config config;
|
||||
std::map<std::string, realm::ObjectDefaults> defaults;
|
||||
std::map<std::string, JSObjectRef> constructors;
|
||||
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);
|
||||
}
|
||||
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());;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
*jsException = RJSMakeError(ctx, "Invalid arguments when constructing 'Realm'");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
config.path = RJSNormalizePath(config.path);
|
||||
|
||||
ensure_directory_exists_for_file(config.path);
|
||||
SharedRealm realm = Realm::get_shared_realm(config);
|
||||
if (!realm->m_binding_context) {
|
||||
realm->m_binding_context.reset(new RJSRealmDelegate(realm, JSContextGetGlobalContext(ctx)));
|
||||
}
|
||||
RJSDefaults(realm.get()) = defaults;
|
||||
RJSConstructors(realm.get()) = constructors;
|
||||
return RJSWrapObject<SharedRealm *>(ctx, RJSRealmClass(), new SharedRealm(realm));
|
||||
}
|
||||
catch (std::exception &ex) {
|
||||
if (jsException) {
|
||||
*jsException = RJSMakeError(ctx, ex);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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}
|
||||
};
|
||||
|
||||
JSValueRef RealmSchemaVersion(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
|
||||
try {
|
||||
RJSValidateArgumentRange(argumentCount, 1, 2);
|
||||
|
||||
Realm::Config config;
|
||||
config.path = RJSNormalizePath(RJSValidatedStringForValue(ctx, arguments[0]));
|
||||
if (argumentCount == 2) {
|
||||
JSValueRef encryptionKeyValue = arguments[1];
|
||||
std::string encryptionKey = RJSAccessor::to_binary(ctx, encryptionKeyValue);
|
||||
config.encryption_key = std::vector<char>(encryptionKey.begin(), encryptionKey.end());
|
||||
}
|
||||
|
||||
auto version = Realm::get_schema_version(config);
|
||||
if (version == ObjectStore::NotVersioned) {
|
||||
return JSValueMakeNumber(ctx, -1);
|
||||
}
|
||||
else {
|
||||
return JSValueMakeNumber(ctx, version);
|
||||
}
|
||||
}
|
||||
catch (std::exception &exp) {
|
||||
if (jsException) {
|
||||
*jsException = RJSMakeError(ctx, exp);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const JSStaticFunction RealmConstructorFuncs[] = {
|
||||
{"schemaVersion", RealmSchemaVersion, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
JSClassRef RJSRealmConstructorClass() {
|
||||
JSClassDefinition realmConstructorDefinition = kJSClassDefinitionEmpty;
|
||||
realmConstructorDefinition.attributes = kJSClassAttributeNoAutomaticPrototype;
|
||||
realmConstructorDefinition.className = "RealmConstructor";
|
||||
realmConstructorDefinition.callAsConstructor = RealmConstructor;
|
||||
realmConstructorDefinition.hasInstance = RealmHasInstance;
|
||||
realmConstructorDefinition.staticValues = RealmStaticProperties;
|
||||
realmConstructorDefinition.staticFunctions = RealmConstructorFuncs;
|
||||
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;
|
||||
}
|
||||
|
||||
std::string RJSValidatedObjectTypeForValue(SharedRealm &realm, JSContextRef ctx, JSValueRef value) {
|
||||
if (JSValueIsObject(ctx, value) && JSObjectIsConstructor(ctx, (JSObjectRef)value)) {
|
||||
JSObjectRef constructor = (JSObjectRef)value;
|
||||
|
||||
for (auto pair : RJSConstructors(realm.get())) {
|
||||
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");
|
||||
}
|
||||
|
||||
JSValueRef RealmObjects(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
|
||||
try {
|
||||
RJSValidateArgumentCount(argumentCount, 1);
|
||||
|
||||
SharedRealm sharedRealm = *RJSGetInternal<SharedRealm *>(thisObject);
|
||||
std::string className = RJSValidatedObjectTypeForValue(sharedRealm, ctx, arguments[0]);
|
||||
return RJSResultsCreate(ctx, sharedRealm, className);
|
||||
}
|
||||
catch (std::exception &exp) {
|
||||
if (jsException) {
|
||||
*jsException = RJSMakeError(ctx, exp);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
JSObjectRef RJSDictForPropertyArray(JSContextRef ctx, const ObjectSchema &object_schema, JSObjectRef array) {
|
||||
// copy to dictionary
|
||||
if (object_schema.properties.size() != RJSValidatedListLength(ctx, array)) {
|
||||
throw std::runtime_error("Array must contain values for all object properties");
|
||||
}
|
||||
|
||||
JSValueRef exception = NULL;
|
||||
JSObjectRef dict = JSObjectMake(ctx, NULL, NULL);
|
||||
for (unsigned int i = 0; i < object_schema.properties.size(); i++) {
|
||||
JSStringRef nameStr = JSStringCreateWithUTF8CString(object_schema.properties[i].name.c_str());
|
||||
JSValueRef value = JSObjectGetPropertyAtIndex(ctx, array, i, &exception);
|
||||
if (exception) {
|
||||
throw RJSException(ctx, exception);
|
||||
}
|
||||
JSObjectSetProperty(ctx, dict, nameStr, value, kJSPropertyAttributeNone, &exception);
|
||||
if (exception) {
|
||||
throw RJSException(ctx, exception);
|
||||
}
|
||||
JSStringRelease(nameStr);
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
|
||||
JSValueRef RealmCreateObject(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
|
||||
try {
|
||||
RJSValidateArgumentRange(argumentCount, 2, 3);
|
||||
|
||||
SharedRealm sharedRealm = *RJSGetInternal<SharedRealm *>(thisObject);
|
||||
std::string className = RJSValidatedObjectTypeForValue(sharedRealm, ctx, arguments[0]);
|
||||
auto &schema = sharedRealm->config().schema;
|
||||
auto object_schema = schema->find(className);
|
||||
|
||||
if (object_schema == schema->end()) {
|
||||
*jsException = RJSMakeError(ctx, "Object type '" + className + "' not found in schema.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSObjectRef object = RJSValidatedValueToObject(ctx, arguments[1]);
|
||||
if (RJSIsValueArray(ctx, arguments[1])) {
|
||||
object = RJSDictForPropertyArray(ctx, *object_schema, object);
|
||||
}
|
||||
|
||||
bool update = false;
|
||||
if (argumentCount == 3) {
|
||||
update = JSValueToBoolean(ctx, arguments[2]);
|
||||
}
|
||||
|
||||
return RJSObjectCreate(ctx, Object::create<JSValueRef>(ctx, sharedRealm, *object_schema, object, update));
|
||||
}
|
||||
catch (std::exception &exp) {
|
||||
if (jsException) {
|
||||
*jsException = RJSMakeError(ctx, exp);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
JSValueRef RealmDelete(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
|
||||
try {
|
||||
RJSValidateArgumentCount(argumentCount, 1);
|
||||
|
||||
if (RJSIsValueArray(ctx, arguments[0]) ||
|
||||
JSValueIsObjectOfClass(ctx, arguments[0], RJSResultsClass()) ||
|
||||
JSValueIsObjectOfClass(ctx, arguments[0], RJSListClass()))
|
||||
{
|
||||
JSObjectRef array = RJSValidatedValueToObject(ctx, arguments[0]);
|
||||
size_t length = RJSValidatedListLength(ctx, array);
|
||||
for (long i = length-1; i >= 0; i--) {
|
||||
JSValueRef object = RJSValidatedObjectAtIndex(ctx, array, (unsigned int)i);
|
||||
RealmDelete(ctx, function, thisObject, 1, &object, jsException);
|
||||
if (*jsException) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!JSValueIsObjectOfClass(ctx, arguments[0], RJSObjectClass())) {
|
||||
throw std::runtime_error("Argument to 'delete' must be a Realm object or a collection of Realm objects.");
|
||||
}
|
||||
|
||||
Object *object = RJSGetInternal<Object *>(RJSValidatedValueToObject(ctx, arguments[0]));
|
||||
|
||||
SharedRealm realm = *RJSGetInternal<SharedRealm *>(thisObject);
|
||||
|
||||
if (!realm->is_in_transaction()) {
|
||||
throw std::runtime_error("Can only delete objects within a transaction.");
|
||||
}
|
||||
|
||||
realm::TableRef table = ObjectStore::table_for_object_type(realm->read_group(), object->get_object_schema().name);
|
||||
table->move_last_over(object->row().get_index());
|
||||
|
||||
return NULL;
|
||||
}
|
||||
catch (std::exception &exp) {
|
||||
if (jsException) {
|
||||
*jsException = RJSMakeError(ctx, exp);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
JSValueRef RealmDeleteAll(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
|
||||
try {
|
||||
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) {
|
||||
ObjectStore::table_for_object_type(realm->read_group(), objectSchema.name)->clear();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
catch (std::exception &exp) {
|
||||
if (jsException) {
|
||||
*jsException = RJSMakeError(ctx, exp);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
JSValueRef RealmWrite(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
|
||||
try {
|
||||
RJSValidateArgumentCount(argumentCount, 1);
|
||||
|
||||
JSObjectRef object = RJSValidatedValueToFunction(ctx, arguments[0]);
|
||||
SharedRealm realm = *RJSGetInternal<SharedRealm *>(thisObject);
|
||||
realm->begin_transaction();
|
||||
JSObjectCallAsFunction(ctx, object, thisObject, 0, NULL, jsException);
|
||||
if (*jsException) {
|
||||
realm->cancel_transaction();
|
||||
}
|
||||
else {
|
||||
realm->commit_transaction();
|
||||
}
|
||||
}
|
||||
catch (std::exception &exp) {
|
||||
if (jsException) {
|
||||
*jsException = RJSMakeError(ctx, exp);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
JSValueRef RealmAddListener(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
|
||||
try {
|
||||
RJSValidateArgumentCount(argumentCount, 2);
|
||||
__unused std::string name = RJSValidatedNotificationName(ctx, arguments[0]);
|
||||
JSObjectRef callback = RJSValidatedValueToFunction(ctx, arguments[1]);
|
||||
|
||||
SharedRealm realm = *RJSGetInternal<SharedRealm *>(thisObject);
|
||||
static_cast<RJSRealmDelegate *>(realm->m_binding_context.get())->add_notification(callback);
|
||||
return NULL;
|
||||
}
|
||||
catch (std::exception &exp) {
|
||||
if (jsException) {
|
||||
*jsException = RJSMakeError(ctx, exp);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
JSValueRef RealmRemoveListener(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
|
||||
try {
|
||||
RJSValidateArgumentCount(argumentCount, 2);
|
||||
__unused std::string name = RJSValidatedNotificationName(ctx, arguments[0]);
|
||||
JSObjectRef callback = RJSValidatedValueToFunction(ctx, arguments[1]);
|
||||
|
||||
SharedRealm realm = *RJSGetInternal<SharedRealm *>(thisObject);
|
||||
static_cast<RJSRealmDelegate *>(realm->m_binding_context.get())->remove_notification(callback);
|
||||
return NULL;
|
||||
}
|
||||
catch (std::exception &exp) {
|
||||
if (jsException) {
|
||||
*jsException = RJSMakeError(ctx, exp);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
JSValueRef RealmRemoveAllListeners(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
|
||||
try {
|
||||
RJSValidateArgumentRange(argumentCount, 0, 1);
|
||||
if (argumentCount) {
|
||||
RJSValidatedNotificationName(ctx, arguments[0]);
|
||||
}
|
||||
|
||||
SharedRealm realm = *RJSGetInternal<SharedRealm *>(thisObject);
|
||||
static_cast<RJSRealmDelegate *>(realm->m_binding_context.get())->remove_all_notifications();
|
||||
return NULL;
|
||||
}
|
||||
catch (std::exception &exp) {
|
||||
if (jsException) {
|
||||
*jsException = RJSMakeError(ctx, exp);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
JSValueRef RealmClose(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
|
||||
try {
|
||||
RJSValidateArgumentCount(argumentCount, 0);
|
||||
SharedRealm realm = *RJSGetInternal<SharedRealm *>(thisObject);
|
||||
realm->close();
|
||||
}
|
||||
catch (std::exception &exp) {
|
||||
if (jsException) {
|
||||
*jsException = RJSMakeError(ctx, exp);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const JSStaticFunction RJSRealmFuncs[] = {
|
||||
{"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},
|
||||
{"addListener", RealmAddListener, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
|
||||
{"removeListener", RealmRemoveListener, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
|
||||
{"removeAllListeners", RealmRemoveAllListeners, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
|
||||
{"close", RealmClose, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
JSClassRef RJSRealmClass() {
|
||||
static JSClassRef s_realmClass = RJSCreateWrapperClass<SharedRealm *>("Realm", RealmGetProperty, NULL, RJSRealmFuncs);
|
||||
return s_realmClass;
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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_util.hpp"
|
||||
#include <map>
|
||||
|
||||
namespace realm {
|
||||
class Realm;
|
||||
using ObjectDefaults = std::map<std::string, JSValueRef>;
|
||||
}
|
||||
|
||||
JSClassRef RJSRealmClass();
|
||||
JSClassRef RJSRealmConstructorClass();
|
||||
|
||||
std::string RJSDefaultPath();
|
||||
void RJSSetDefaultPath(std::string path);
|
||||
|
||||
std::map<std::string, realm::ObjectDefaults> &RJSDefaults(realm::Realm *realm);
|
||||
std::map<std::string, JSObjectRef> &RJSConstructors(realm::Realm *realm);
|
|
@ -0,0 +1,37 @@
|
|||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <JavaScriptCore/JSContextRef.h>
|
||||
#include <JavaScriptCore/JSObjectRef.h>
|
||||
#include <JavaScriptCore/JSStringRef.h>
|
||||
|
||||
namespace realm {
|
||||
namespace js {
|
||||
|
||||
struct Types {
|
||||
using Context = JSContextRef;
|
||||
using Value = JSValueRef;
|
||||
using Object = JSObjectRef;
|
||||
using String = JSStringRef;
|
||||
using Function = JSObjectRef;
|
||||
using Return = JSValueRef;
|
||||
};
|
||||
|
||||
}}
|
Loading…
Reference in New Issue