realm-js/src/js_realm.cpp

452 lines
20 KiB
C++
Raw Normal View History

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
// 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;
}
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;
std::map<std::string, realm::ObjectDefaults> defaults;
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
}
config.path = RJSNormalizePath(config.path);
ensure_directory_exists_for_file(config.path);
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);
}
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;
}
}
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) {
try {
RJSValidateArgumentRange(argumentCount, 1, 2);
Realm::Config config;
config.path = RJSNormalizePath(RJSValidatedStringForValue(ctx, arguments[0]));
if (argumentCount == 2) {
2016-03-29 13:36:01 -07:00
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) {
2016-03-29 13:36:01 -07:00
RJSSetReturnNumber(ctx, returnObject, -1);
}
else {
2016-03-29 13:36:01 -07:00
RJSSetReturnNumber(ctx, returnObject, version);
}
}
catch (std::exception &exp) {
2016-03-29 13:36:01 -07:00
RJSSetException(ctx, exceptionObject, exp);
}
}
2016-03-29 13:36:01 -07:00
WRAP_METHOD(RealmSchemaVersion)
static const JSStaticFunction RealmConstructorFuncs[] = {
{"schemaVersion", RealmSchemaVersion, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{NULL, NULL},
};
2015-08-13 09:12:48 -07:00
JSClassRef RJSRealmConstructorClass() {
JSClassDefinition realmConstructorDefinition = kJSClassDefinitionEmpty;
realmConstructorDefinition.attributes = kJSClassAttributeNoAutomaticPrototype;
realmConstructorDefinition.className = "RealmConstructor";
2015-08-13 09:12:48 -07:00
realmConstructorDefinition.callAsConstructor = RealmConstructor;
realmConstructorDefinition.hasInstance = RealmHasInstance;
realmConstructorDefinition.staticValues = RealmStaticProperties;
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;
}
std::string RJSValidatedObjectTypeForValue(SharedRealm &realm, JSContextRef ctx, JSValueRef value) {
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) {
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 {
RJSValidateArgumentCount(argumentCount, 1);
2015-08-13 09:12:48 -07:00
SharedRealm sharedRealm = *RJSGetInternal<SharedRealm *>(thisObject);
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);
std::string className = RJSValidatedObjectTypeForValue(sharedRealm, ctx, arguments[0]);
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);
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.");
}
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)
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},
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},
{NULL, NULL},
};
2015-08-13 09:12:48 -07:00
JSClassRef RJSRealmClass() {
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(); };
}
}