key templates off explicitly defined classes rather than the internal type

This commit is contained in:
Ari Lazier 2016-04-15 13:47:01 -07:00
parent 760126f0d7
commit bd4088ce91
11 changed files with 148 additions and 114 deletions

View File

@ -70,6 +70,8 @@ using PropertyMap = std::map<std::string, PropertyType<T>>;
template<typename T, typename U> template<typename T, typename U>
struct ClassDefinition { struct ClassDefinition {
using Internal = U;
// Every specialization *must* at least have a name. // Every specialization *must* at least have a name.
std::string name; std::string name;
}; };
@ -89,7 +91,7 @@ struct BaseClassDefinition {
StringPropertyType<T> string_accessor; StringPropertyType<T> string_accessor;
}; };
template<typename T, typename U> template<typename T, typename ClassType>
class ObjectWrap; class ObjectWrap;
} // js } // js

View File

@ -27,7 +27,7 @@ namespace js {
class Collection {}; class Collection {};
template<typename T> template<typename T>
struct ClassDefinition<T, Collection> : BaseClassDefinition<T> { struct CollectionClass : ClassDefinition<T, Collection>, BaseClassDefinition<T> {
std::string const name = "Collection"; std::string const name = "Collection";
}; };

View File

@ -58,7 +58,7 @@ struct List {
}; };
template<typename T> template<typename T>
struct ClassDefinition<T, realm::List> : BaseClassDefinition<T, Collection> { struct ListClass : ClassDefinition<T, realm::List>, BaseClassDefinition<T, CollectionClass<T>> {
using List = List<T>; using List = List<T>;
std::string const name = "List"; std::string const name = "List";
@ -83,18 +83,18 @@ struct ClassDefinition<T, realm::List> : BaseClassDefinition<T, Collection> {
template<typename T> template<typename T>
typename T::Object List<T>::create_instance(TContext ctx, realm::List &list) { typename T::Object List<T>::create_instance(TContext ctx, realm::List &list) {
return create_object<T, realm::List>(ctx, new realm::List(list)); return create_object<T, ListClass<T>>(ctx, new realm::List(list));
} }
template<typename T> template<typename T>
void List<T>::GetLength(TContext ctx, TObject object, ReturnValue &return_value) { void List<T>::GetLength(TContext ctx, TObject object, ReturnValue &return_value) {
auto list = get_internal<T, realm::List>(object); auto list = get_internal<T, ListClass<T>>(object);
return_value.set((uint32_t)list->size()); return_value.set((uint32_t)list->size());
} }
template<typename T> template<typename T>
void List<T>::GetIndex(TContext ctx, TObject object, uint32_t index, ReturnValue &return_value) { void List<T>::GetIndex(TContext ctx, TObject object, uint32_t index, ReturnValue &return_value) {
auto list = get_internal<T, realm::List>(object); auto list = get_internal<T, ListClass<T>>(object);
auto realm_object = realm::Object(list->get_realm(), list->get_object_schema(), list->get(index)); auto realm_object = realm::Object(list->get_realm(), list->get_object_schema(), list->get(index));
return_value.set(RealmObject<T>::create_instance(ctx, realm_object)); return_value.set(RealmObject<T>::create_instance(ctx, realm_object));
@ -102,7 +102,7 @@ void List<T>::GetIndex(TContext ctx, TObject object, uint32_t index, ReturnValue
template<typename T> template<typename T>
bool List<T>::SetIndex(TContext ctx, TObject object, uint32_t index, TValue value) { bool List<T>::SetIndex(TContext ctx, TObject object, uint32_t index, TValue value) {
auto list = get_internal<T, realm::List>(object); auto list = get_internal<T, ListClass<T>>(object);
list->set(ctx, value, index); list->set(ctx, value, index);
return true; return true;
} }
@ -111,7 +111,7 @@ template<typename T>
void List<T>::Push(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { void List<T>::Push(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) {
validate_argument_count_at_least(argc, 1); validate_argument_count_at_least(argc, 1);
auto list = get_internal<T, realm::List>(this_object); auto list = get_internal<T, ListClass<T>>(this_object);
for (size_t i = 0; i < argc; i++) { for (size_t i = 0; i < argc; i++) {
list->add(ctx, arguments[i]); list->add(ctx, arguments[i]);
} }
@ -123,7 +123,7 @@ template<typename T>
void List<T>::Pop(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { void List<T>::Pop(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) {
validate_argument_count(argc, 0); validate_argument_count(argc, 0);
auto list = get_internal<T, realm::List>(this_object); auto list = get_internal<T, ListClass<T>>(this_object);
size_t size = list->size(); size_t size = list->size();
if (size == 0) { if (size == 0) {
list->verify_in_transaction(); list->verify_in_transaction();
@ -142,7 +142,7 @@ template<typename T>
void List<T>::Unshift(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { void List<T>::Unshift(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) {
validate_argument_count_at_least(argc, 1); validate_argument_count_at_least(argc, 1);
auto list = get_internal<T, realm::List>(this_object); auto list = get_internal<T, ListClass<T>>(this_object);
for (size_t i = 0; i < argc; i++) { for (size_t i = 0; i < argc; i++) {
list->insert(ctx, arguments[i], i); list->insert(ctx, arguments[i], i);
} }
@ -154,7 +154,7 @@ template<typename T>
void List<T>::Shift(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { void List<T>::Shift(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) {
validate_argument_count(argc, 0); validate_argument_count(argc, 0);
auto list = get_internal<T, realm::List>(this_object); auto list = get_internal<T, ListClass<T>>(this_object);
if (list->size() == 0) { if (list->size() == 0) {
list->verify_in_transaction(); list->verify_in_transaction();
return_value.set_undefined(); return_value.set_undefined();
@ -171,7 +171,7 @@ template<typename T>
void List<T>::Splice(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { void List<T>::Splice(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) {
validate_argument_count_at_least(argc, 1); validate_argument_count_at_least(argc, 1);
auto list = get_internal<T, realm::List>(this_object); auto list = get_internal<T, ListClass<T>>(this_object);
size_t size = list->size(); size_t size = list->size();
long index = std::min<long>(Value::to_number(ctx, arguments[0]), size); long index = std::min<long>(Value::to_number(ctx, arguments[0]), size);
if (index < 0) { if (index < 0) {
@ -207,7 +207,7 @@ template<typename T>
void List<T>::StaticResults(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { void List<T>::StaticResults(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) {
validate_argument_count(argc, 0); validate_argument_count(argc, 0);
auto list = get_internal<T, realm::List>(this_object); auto list = get_internal<T, ListClass<T>>(this_object);
return_value.set(Results<T>::create_instance(ctx, *list, false)); return_value.set(Results<T>::create_instance(ctx, *list, false));
} }
@ -215,7 +215,7 @@ template<typename T>
void List<T>::Filtered(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { void List<T>::Filtered(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) {
validate_argument_count_at_least(argc, 1); validate_argument_count_at_least(argc, 1);
auto list = get_internal<T, realm::List>(this_object); auto list = get_internal<T, ListClass<T>>(this_object);
return_value.set(Results<T>::create_filtered(ctx, *list, argc, arguments)); return_value.set(Results<T>::create_filtered(ctx, *list, argc, arguments));
} }
@ -223,7 +223,7 @@ template<typename T>
void List<T>::Sorted(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { void List<T>::Sorted(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) {
validate_argument_count(argc, 1, 2); validate_argument_count(argc, 1, 2);
auto list = get_internal<T, realm::List>(this_object); auto list = get_internal<T, ListClass<T>>(this_object);
return_value.set(Results<T>::create_sorted(ctx, *list, argc, arguments)); return_value.set(Results<T>::create_sorted(ctx, *list, argc, arguments));
} }

View File

@ -48,7 +48,7 @@ struct RealmObject {
}; };
template<typename T> template<typename T>
struct ClassDefinition<T, realm::Object> : BaseClassDefinition<T> { struct RealmObjectClass : ClassDefinition<T, realm::Object>, BaseClassDefinition<T> {
using RealmObject = RealmObject<T>; using RealmObject = RealmObject<T>;
const std::string name = "RealmObject"; const std::string name = "RealmObject";
@ -66,7 +66,7 @@ typename T::Object RealmObject<T>::create_instance(TContext ctx, realm::Object &
auto delegate = get_delegate<T>(realm_object.realm().get()); auto delegate = get_delegate<T>(realm_object.realm().get());
auto name = realm_object.get_object_schema().name; auto name = realm_object.get_object_schema().name;
auto object = create_object<T, realm::Object>(ctx, new realm::Object(realm_object)); auto object = create_object<T, RealmObjectClass<T>>(ctx, new realm::Object(realm_object));
if (!delegate->m_constructors.count(name)) { if (!delegate->m_constructors.count(name)) {
return object; return object;
@ -87,7 +87,7 @@ typename T::Object RealmObject<T>::create_instance(TContext ctx, realm::Object &
template<typename T> template<typename T>
void RealmObject<T>::GetProperty(TContext ctx, TObject object, const String &property, ReturnValue &return_value) { void RealmObject<T>::GetProperty(TContext ctx, TObject object, const String &property, ReturnValue &return_value) {
try { try {
auto realm_object = get_internal<T, realm::Object>(object); auto realm_object = get_internal<T, RealmObjectClass<T>>(object);
auto result = realm_object->template get_property_value<TValue>(ctx, property); auto result = realm_object->template get_property_value<TValue>(ctx, property);
return_value.set(result); return_value.set(result);
} catch (InvalidPropertyException &ex) { } catch (InvalidPropertyException &ex) {
@ -97,14 +97,14 @@ void RealmObject<T>::GetProperty(TContext ctx, TObject object, const String &pro
template<typename T> template<typename T>
bool RealmObject<T>::SetProperty(TContext ctx, TObject object, const String &property, TValue value) { bool RealmObject<T>::SetProperty(TContext ctx, TObject object, const String &property, TValue value) {
auto realm_object = get_internal<T, realm::Object>(object); auto realm_object = get_internal<T, RealmObjectClass<T>>(object);
realm_object->set_property_value(ctx, property, value, true); realm_object->set_property_value(ctx, property, value, true);
return true; return true;
} }
template<typename T> template<typename T>
std::vector<String<T>> RealmObject<T>::GetPropertyNames(TContext ctx, TObject object) { std::vector<String<T>> RealmObject<T>::GetPropertyNames(TContext ctx, TObject object) {
auto realm_object = get_internal<T, realm::Object>(object); auto realm_object = get_internal<T, RealmObjectClass<T>>(object);
auto &properties = realm_object->get_object_schema().properties; auto &properties = realm_object->get_object_schema().properties;
std::vector<String> names; std::vector<String> names;

View File

@ -102,8 +102,8 @@ struct NativeAccessor {
static size_t to_object_index(TContext ctx, SharedRealm realm, TValue &value, const std::string &type, bool try_update) { static size_t to_object_index(TContext ctx, SharedRealm realm, TValue &value, const std::string &type, bool try_update) {
TObject object = Value::validated_to_object(ctx, value); TObject object = Value::validated_to_object(ctx, value);
if (Object::template is_instance<realm::Object>(ctx, object)) { if (Object::template is_instance<RealmObjectClass<T>>(ctx, object)) {
return get_internal<T, realm::Object>(object)->row().get_index(); return get_internal<T, RealmObjectClass<T>>(object)->row().get_index();
} }
auto object_schema = realm->config().schema->find(type); auto object_schema = realm->config().schema->find(type);
@ -116,8 +116,8 @@ struct NativeAccessor {
} }
static size_t to_existing_object_index(TContext ctx, TValue &value) { static size_t to_existing_object_index(TContext ctx, TValue &value) {
TObject object = Value::validated_to_object(ctx, value); TObject object = Value::validated_to_object(ctx, value);
if (Object::template is_instance<realm::Object>(ctx, object)) { if (Object::template is_instance<RealmObjectClass<T>>(ctx, object)) {
return get_internal<T, realm::Object>(object)->row().get_index(); return get_internal<T, RealmObjectClass<T>>(object)->row().get_index();
} }
throw std::runtime_error("object is not a Realm Object"); throw std::runtime_error("object is not a Realm Object");
} }

View File

@ -37,6 +37,9 @@
namespace realm { namespace realm {
namespace js { namespace js {
template<typename T>
struct RealmClass;
template<typename T> template<typename T>
class RealmDelegate : public BindingContext { class RealmDelegate : public BindingContext {
public: public:
@ -87,7 +90,7 @@ class RealmDelegate : public BindingContext {
throw std::runtime_error("Realm no longer exists"); throw std::runtime_error("Realm no longer exists");
} }
TObject realm_object = create_object<T, SharedRealm>(m_context, new SharedRealm(realm)); TObject realm_object = create_object<T, RealmClass<T>>(m_context, new SharedRealm(realm));
TValue arguments[2]; TValue arguments[2];
arguments[0] = realm_object; arguments[0] = realm_object;
arguments[1] = Value::from_string(m_context, notification_name); arguments[1] = Value::from_string(m_context, notification_name);
@ -140,10 +143,10 @@ class Realm {
static void SetDefaultPath(TContext, TObject, TValue value); static void SetDefaultPath(TContext, TObject, TValue value);
static TObject create_constructor(TContext ctx) { static TObject create_constructor(TContext ctx) {
TObject realm_constructor = ObjectWrap<T, SharedRealm>::create_constructor(ctx); TObject realm_constructor = ObjectWrap<T, RealmClass<T>>::create_constructor(ctx);
TObject collection_constructor = ObjectWrap<T, Collection>::create_constructor(ctx); TObject collection_constructor = ObjectWrap<T, CollectionClass<T>>::create_constructor(ctx);
TObject list_constructor = ObjectWrap<T, realm::List>::create_constructor(ctx); TObject list_constructor = ObjectWrap<T, ListClass<T>>::create_constructor(ctx);
TObject results_constructor = ObjectWrap<T, realm::Results>::create_constructor(ctx); TObject results_constructor = ObjectWrap<T, ResultsClass<T>>::create_constructor(ctx);
PropertyAttributes attributes = PropertyAttributes(ReadOnly | DontEnum | DontDelete); PropertyAttributes attributes = PropertyAttributes(ReadOnly | DontEnum | DontDelete);
Object::set_property(ctx, realm_constructor, "Collection", collection_constructor, attributes); Object::set_property(ctx, realm_constructor, "Collection", collection_constructor, attributes);
@ -186,7 +189,7 @@ class Realm {
}; };
template<typename T> template<typename T>
struct ClassDefinition<T, SharedRealm> : BaseClassDefinition<T> { struct RealmClass : ClassDefinition<T, SharedRealm>, BaseClassDefinition<T> {
using Realm = Realm<T>; using Realm = Realm<T>;
std::string const name = "Realm"; std::string const name = "Realm";
@ -288,7 +291,7 @@ void Realm<T>::Constructor(TContext ctx, TObject this_object, size_t argc, const
delegate->m_defaults = std::move(defaults); delegate->m_defaults = std::move(defaults);
delegate->m_constructors = std::move(constructors); delegate->m_constructors = std::move(constructors);
set_internal<T, SharedRealm>(this_object, new SharedRealm(realm)); set_internal<T, RealmClass<T>>(this_object, new SharedRealm(realm));
} }
template<typename T> template<typename T>
@ -330,13 +333,13 @@ void Realm<T>::SetDefaultPath(TContext ctx, TObject object, TValue value) {
template<typename T> template<typename T>
void Realm<T>::GetPath(TContext ctx, TObject object, ReturnValue &return_value) { void Realm<T>::GetPath(TContext ctx, TObject object, ReturnValue &return_value) {
std::string path = get_internal<T, SharedRealm>(object)->get()->config().path; std::string path = get_internal<T, RealmClass<T>>(object)->get()->config().path;
return_value.set(path); return_value.set(path);
} }
template<typename T> template<typename T>
void Realm<T>::GetSchemaVersion(TContext ctx, TObject object, ReturnValue &return_value) { void Realm<T>::GetSchemaVersion(TContext ctx, TObject object, ReturnValue &return_value) {
double version = get_internal<T, SharedRealm>(object)->get()->config().schema_version; double version = get_internal<T, RealmClass<T>>(object)->get()->config().schema_version;
return_value.set(version); return_value.set(version);
} }
@ -344,7 +347,7 @@ template<typename T>
void Realm<T>::Objects(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { void Realm<T>::Objects(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) {
validate_argument_count(argc, 1); validate_argument_count(argc, 1);
SharedRealm realm = *get_internal<T, SharedRealm>(this_object); SharedRealm realm = *get_internal<T, RealmClass<T>>(this_object);
std::string type = validated_object_type_for_value(realm, ctx, arguments[0]); std::string type = validated_object_type_for_value(realm, ctx, arguments[0]);
return_value.set(Results<T>::create_instance(ctx, realm, type)); return_value.set(Results<T>::create_instance(ctx, realm, type));
@ -354,7 +357,7 @@ template<typename T>
void Realm<T>::Create(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { void Realm<T>::Create(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) {
validate_argument_count(argc, 2, 3); validate_argument_count(argc, 2, 3);
SharedRealm sharedRealm = *get_internal<T, SharedRealm>(this_object); SharedRealm sharedRealm = *get_internal<T, RealmClass<T>>(this_object);
std::string className = validated_object_type_for_value(sharedRealm, ctx, arguments[0]); std::string className = validated_object_type_for_value(sharedRealm, ctx, arguments[0]);
auto &schema = sharedRealm->config().schema; auto &schema = sharedRealm->config().schema;
auto object_schema = schema->find(className); auto object_schema = schema->find(className);
@ -381,15 +384,15 @@ template<typename T>
void Realm<T>::Delete(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { void Realm<T>::Delete(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) {
validate_argument_count(argc, 1); validate_argument_count(argc, 1);
SharedRealm realm = *get_internal<T, SharedRealm>(this_object); SharedRealm realm = *get_internal<T, RealmClass<T>>(this_object);
if (!realm->is_in_transaction()) { if (!realm->is_in_transaction()) {
throw std::runtime_error("Can only delete objects within a transaction."); throw std::runtime_error("Can only delete objects within a transaction.");
} }
TObject arg = Value::validated_to_object(ctx, arguments[0]); TObject arg = Value::validated_to_object(ctx, arguments[0]);
if (Object::template is_instance<realm::Object>(ctx, arg)) { if (Object::template is_instance<RealmObjectClass<T>>(ctx, arg)) {
auto object = get_internal<T, realm::Object>(arg); auto object = get_internal<T, RealmObjectClass<T>>(arg);
realm::TableRef table = ObjectStore::table_for_object_type(realm->read_group(), object->get_object_schema().name); realm::TableRef table = ObjectStore::table_for_object_type(realm->read_group(), object->get_object_schema().name);
table->move_last_over(object->row().get_index()); table->move_last_over(object->row().get_index());
} }
@ -398,21 +401,21 @@ void Realm<T>::Delete(TContext ctx, TObject this_object, size_t argc, const TVal
for (uint32_t i = length; i--;) { for (uint32_t i = length; i--;) {
TObject object = Object::validated_get_object(ctx, arg, i); TObject object = Object::validated_get_object(ctx, arg, i);
if (!Object::template is_instance<realm::Object>(ctx, object)) { if (!Object::template is_instance<RealmObjectClass<T>>(ctx, object)) {
throw std::runtime_error("Argument to 'delete' must be a Realm object or a collection of Realm objects."); throw std::runtime_error("Argument to 'delete' must be a Realm object or a collection of Realm objects.");
} }
auto realm_object = get_internal<T, realm::Object>(object); auto realm_object = get_internal<T, RealmObjectClass<T>>(object);
realm::TableRef table = ObjectStore::table_for_object_type(realm->read_group(), realm_object->get_object_schema().name); realm::TableRef table = ObjectStore::table_for_object_type(realm->read_group(), realm_object->get_object_schema().name);
table->move_last_over(realm_object->row().get_index()); table->move_last_over(realm_object->row().get_index());
} }
} }
else if (Object::template is_instance<realm::Results>(ctx, arg)) { else if (Object::template is_instance<ResultsClass<T>>(ctx, arg)) {
auto results = get_internal<T, realm::Results>(arg); auto results = get_internal<T, ResultsClass<T>>(arg);
results->clear(); results->clear();
} }
else if (Object::template is_instance<realm::List>(ctx, arg)) { else if (Object::template is_instance<ListClass<T>>(ctx, arg)) {
auto list = get_internal<T, realm::List>(arg); auto list = get_internal<T, ListClass<T>>(arg);
list->delete_all(); list->delete_all();
} }
else { else {
@ -424,7 +427,7 @@ template<typename T>
void Realm<T>::DeleteAll(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { void Realm<T>::DeleteAll(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) {
validate_argument_count(argc, 0); validate_argument_count(argc, 0);
SharedRealm realm = *get_internal<T, SharedRealm>(this_object); SharedRealm realm = *get_internal<T, RealmClass<T>>(this_object);
if (!realm->is_in_transaction()) { if (!realm->is_in_transaction()) {
throw std::runtime_error("Can only delete objects within a transaction."); throw std::runtime_error("Can only delete objects within a transaction.");
@ -439,7 +442,7 @@ template<typename T>
void Realm<T>::Write(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { void Realm<T>::Write(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) {
validate_argument_count(argc, 1); validate_argument_count(argc, 1);
SharedRealm realm = *get_internal<T, SharedRealm>(this_object); SharedRealm realm = *get_internal<T, RealmClass<T>>(this_object);
TFunction callback = Value::validated_to_function(ctx, arguments[0]); TFunction callback = Value::validated_to_function(ctx, arguments[0]);
try { try {
@ -462,7 +465,7 @@ void Realm<T>::AddListener(TContext ctx, TObject this_object, size_t argc, const
__unused std::string name = validated_notification_name(ctx, arguments[0]); __unused std::string name = validated_notification_name(ctx, arguments[0]);
auto callback = Value::validated_to_function(ctx, arguments[1]); auto callback = Value::validated_to_function(ctx, arguments[1]);
SharedRealm realm = *get_internal<T, SharedRealm>(this_object); SharedRealm realm = *get_internal<T, RealmClass<T>>(this_object);
get_delegate<T>(realm.get())->add_notification(callback); get_delegate<T>(realm.get())->add_notification(callback);
} }
@ -473,7 +476,7 @@ void Realm<T>::RemoveListener(TContext ctx, TObject this_object, size_t argc, co
__unused std::string name = validated_notification_name(ctx, arguments[0]); __unused std::string name = validated_notification_name(ctx, arguments[0]);
auto callback = Value::validated_to_function(ctx, arguments[1]); auto callback = Value::validated_to_function(ctx, arguments[1]);
SharedRealm realm = *get_internal<T, SharedRealm>(this_object); SharedRealm realm = *get_internal<T, RealmClass<T>>(this_object);
get_delegate<T>(realm.get())->remove_notification(callback); get_delegate<T>(realm.get())->remove_notification(callback);
} }
@ -484,7 +487,7 @@ void Realm<T>::RemoveAllListeners(TContext ctx, TObject this_object, size_t argc
validated_notification_name(ctx, arguments[0]); validated_notification_name(ctx, arguments[0]);
} }
SharedRealm realm = *get_internal<T, SharedRealm>(this_object); SharedRealm realm = *get_internal<T, RealmClass<T>>(this_object);
get_delegate<T>(realm.get())->remove_all_notifications(); get_delegate<T>(realm.get())->remove_all_notifications();
} }
@ -492,7 +495,7 @@ template<typename T>
void Realm<T>::Close(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { void Realm<T>::Close(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) {
validate_argument_count(argc, 0); validate_argument_count(argc, 0);
SharedRealm realm = *get_internal<T, SharedRealm>(this_object); SharedRealm realm = *get_internal<T, RealmClass<T>>(this_object);
realm->close(); realm->close();
} }

View File

@ -58,7 +58,7 @@ struct Results {
}; };
template<typename T> template<typename T>
struct ClassDefinition<T, realm::Results> : BaseClassDefinition<T, Collection> { struct ResultsClass : ClassDefinition<T, realm::Results>, BaseClassDefinition<T, CollectionClass<T>> {
using Results = Results<T>; using Results = Results<T>;
std::string const name = "Results"; std::string const name = "Results";
@ -81,7 +81,7 @@ typename T::Object Results<T>::create_instance(TContext ctx, const realm::Result
auto new_results = new realm::Results(results); auto new_results = new realm::Results(results);
new_results->set_live(live); new_results->set_live(live);
return create_object<T, realm::Results>(ctx, new_results); return create_object<T, ResultsClass<T>>(ctx, new_results);
} }
template<typename T> template<typename T>
@ -102,7 +102,7 @@ typename T::Object Results<T>::create_instance(TContext ctx, SharedRealm realm,
auto results = new realm::Results(realm, *object_schema, *table); auto results = new realm::Results(realm, *object_schema, *table);
results->set_live(live); results->set_live(live);
return create_object<T, realm::Results>(ctx, results); return create_object<T, ResultsClass<T>>(ctx, results);
} }
template<typename T> template<typename T>
@ -110,7 +110,7 @@ typename T::Object Results<T>::create_instance(TContext ctx, SharedRealm realm,
auto results = new realm::Results(realm, object_schema, std::move(query)); auto results = new realm::Results(realm, object_schema, std::move(query));
results->set_live(live); results->set_live(live);
return create_object<T, realm::Results>(ctx, results); return create_object<T, ResultsClass<T>>(ctx, results);
} }
template<typename T> template<typename T>
@ -190,18 +190,18 @@ typename T::Object Results<T>::create_sorted(TContext ctx, const U &collection,
} }
auto results = new realm::Results(realm, object_schema, collection.get_query(), {std::move(columns), std::move(ascending)}); auto results = new realm::Results(realm, object_schema, collection.get_query(), {std::move(columns), std::move(ascending)});
return create_object<T, realm::Results>(ctx, results); return create_object<T, ResultsClass<T>>(ctx, results);
} }
template<typename T> template<typename T>
void Results<T>::GetLength(TContext ctx, TObject object, ReturnValue &return_value) { void Results<T>::GetLength(TContext ctx, TObject object, ReturnValue &return_value) {
auto results = get_internal<T, realm::Results>(object); auto results = get_internal<T, ResultsClass<T>>(object);
return_value.set((uint32_t)results->size()); return_value.set((uint32_t)results->size());
} }
template<typename T> template<typename T>
void Results<T>::GetIndex(TContext ctx, TObject object, uint32_t index, ReturnValue &return_value) { void Results<T>::GetIndex(TContext ctx, TObject object, uint32_t index, ReturnValue &return_value) {
auto results = get_internal<T, realm::Results>(object); auto results = get_internal<T, ResultsClass<T>>(object);
auto row = results->get(index); auto row = results->get(index);
// Return null for deleted objects in a snapshot. // Return null for deleted objects in a snapshot.
@ -218,7 +218,7 @@ template<typename T>
void Results<T>::StaticResults(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { void Results<T>::StaticResults(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) {
validate_argument_count(argc, 0); validate_argument_count(argc, 0);
auto results = get_internal<T, realm::Results>(this_object); auto results = get_internal<T, ResultsClass<T>>(this_object);
return_value.set(Results<T>::create_instance(ctx, *results, false)); return_value.set(Results<T>::create_instance(ctx, *results, false));
} }
@ -226,7 +226,7 @@ template<typename T>
void Results<T>::Filtered(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { void Results<T>::Filtered(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) {
validate_argument_count_at_least(argc, 1); validate_argument_count_at_least(argc, 1);
auto results = get_internal<T, realm::Results>(this_object); auto results = get_internal<T, ResultsClass<T>>(this_object);
return_value.set(create_filtered(ctx, *results, argc, arguments)); return_value.set(create_filtered(ctx, *results, argc, arguments));
} }
@ -234,7 +234,7 @@ template<typename T>
void Results<T>::Sorted(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { void Results<T>::Sorted(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) {
validate_argument_count(argc, 1, 2); validate_argument_count(argc, 1, 2);
auto results = get_internal<T, realm::Results>(this_object); auto results = get_internal<T, ResultsClass<T>>(this_object);
return_value.set(create_sorted(ctx, *results, argc, arguments)); return_value.set(create_sorted(ctx, *results, argc, arguments));
} }

View File

@ -219,17 +219,17 @@ struct Object {
static TObject create_date(TContext, double); static TObject create_date(TContext, double);
template<typename U> template<typename ClassType>
static TObject create_instance(TContext, U*); static TObject create_instance(TContext, typename ClassType::Internal*);
template<typename U> template<typename ClassType>
static bool is_instance(TContext, const TObject &); static bool is_instance(TContext, const TObject &);
template<typename U> template<typename ClassType>
static U* get_internal(const TObject &); static typename ClassType::Internal* get_internal(const TObject &);
template<typename U> template<typename ClassType>
static void set_internal(const TObject &, U*); static void set_internal(const TObject &, typename ClassType::Internal*);
}; };
template<typename TValue> template<typename TValue>
@ -280,19 +280,19 @@ struct ReturnValue {
void set_undefined(); void set_undefined();
}; };
template<typename T, typename U> template<typename T, typename ClassType>
REALM_JS_INLINE typename T::Object create_object(typename T::Context ctx, U* internal = nullptr) { REALM_JS_INLINE typename T::Object create_object(typename T::Context ctx, typename ClassType::Internal* internal = nullptr) {
return Object<T>::template create_instance<U>(ctx, internal); return Object<T>::template create_instance<ClassType>(ctx, internal);
} }
template<typename T, typename U> template<typename T, typename ClassType>
REALM_JS_INLINE U* get_internal(const typename T::Object &object) { REALM_JS_INLINE typename ClassType::Internal* get_internal(const typename T::Object &object) {
return Object<T>::template get_internal<U>(object); return Object<T>::template get_internal<ClassType>(object);
} }
template<typename T, typename U> template<typename T, typename ClassType>
REALM_JS_INLINE void set_internal(const typename T::Object &object, U* ptr) { REALM_JS_INLINE void set_internal(const typename T::Object &object, typename ClassType::Internal* ptr) {
Object<T>::template set_internal<U>(object, ptr); Object<T>::template set_internal<ClassType>(object, ptr);
} }
} // js } // js

View File

@ -28,7 +28,6 @@ namespace jsc {
template<typename T> template<typename T>
using ClassDefinition = js::ClassDefinition<Types, T>; using ClassDefinition = js::ClassDefinition<Types, T>;
using BaseClassDefinition = js::BaseClassDefinition<Types>;
using ConstructorType = js::ConstructorType<Types>; using ConstructorType = js::ConstructorType<Types>;
using MethodType = js::MethodType<Types>; using MethodType = js::MethodType<Types>;
using PropertyType = js::PropertyType<Types>; using PropertyType = js::PropertyType<Types>;
@ -37,15 +36,16 @@ using StringPropertyType = js::StringPropertyType<Types>;
using MethodMap = js::MethodMap<Types>; using MethodMap = js::MethodMap<Types>;
using PropertyMap = js::PropertyMap<Types>; using PropertyMap = js::PropertyMap<Types>;
template<typename T> template<typename ClassType>
class ObjectWrap { class ObjectWrap {
public: public:
operator T*() const { using Internal = typename ClassType::Internal;
operator Internal*() const {
return m_object.get(); return m_object.get();
} }
ObjectWrap<T>& operator=(T* object) { ObjectWrap<ClassType>& operator=(Internal* object) {
if (m_object.get() != object) { if (m_object.get() != object) {
m_object = std::unique_ptr<T>(object); m_object = std::unique_ptr<Internal>(object);
} }
return *this; return *this;
} }
@ -60,8 +60,8 @@ public:
return js_class; return js_class;
} }
static JSObjectRef create_instance(JSContextRef ctx, T* internal = nullptr) { static JSObjectRef create_instance(JSContextRef ctx, Internal* internal = nullptr) {
return JSObjectMake(ctx, get_class(), new ObjectWrap<T>(internal)); return JSObjectMake(ctx, get_class(), new ObjectWrap<ClassType>(internal));
} }
static JSObjectRef create_constructor(JSContextRef ctx) { static JSObjectRef create_constructor(JSContextRef ctx) {
@ -77,11 +77,11 @@ public:
} }
private: private:
static ClassDefinition<T> s_class; static ClassType s_class;
std::unique_ptr<T> m_object; std::unique_ptr<Internal> m_object;
ObjectWrap(T* object = nullptr) : m_object(object) {} ObjectWrap(Internal* object = nullptr) : m_object(object) {}
static JSObjectRef construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef arguments[], JSValueRef* exception) { static JSObjectRef construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef arguments[], JSValueRef* exception) {
if (!s_class.constructor) { if (!s_class.constructor) {
@ -89,7 +89,7 @@ private:
return nullptr; return nullptr;
} }
JSObjectRef this_object = ObjectWrap<T>::create_instance(ctx); JSObjectRef this_object = ObjectWrap<ClassType>::create_instance(ctx);
try { try {
s_class.constructor(ctx, this_object, argc, arguments); s_class.constructor(ctx, this_object, argc, arguments);
} }
@ -178,7 +178,7 @@ private:
static void finalize(JSObjectRef object) { static void finalize(JSObjectRef object) {
// This is called for the most derived class before superclasses. // This is called for the most derived class before superclasses.
if (auto wrap = static_cast<ObjectWrap<T> *>(JSObjectGetPrivate(object))) { if (auto wrap = static_cast<ObjectWrap<ClassType> *>(JSObjectGetPrivate(object))) {
delete wrap; delete wrap;
JSObjectSetPrivate(object, nullptr); JSObjectSetPrivate(object, nullptr);
} }
@ -283,14 +283,42 @@ private:
} }
}; };
// Make the top-level base class return a NULL JSClassRef.
template<> template<>
inline JSClassRef ObjectWrap<void>::get_class() { class ObjectWrap<void> {
return nullptr; public:
} using Internal = void;
operator Internal*() const {
return nullptr;
}
ObjectWrap<void>& operator=(Internal* object) {
return *this;
}
static JSClassRef get_class() {
return nullptr;
}
static JSClassRef get_constructor_class() {
return nullptr;
}
static JSObjectRef create_instance(JSContextRef ctx, Internal* internal = nullptr) {
return nullptr;
}
static JSObjectRef create_constructor(JSContextRef ctx) {
return nullptr;
}
static bool has_instance(JSContextRef ctx, JSValueRef value) {
return nullptr;
}
};
// The declared static variables must be defined as well. // The declared static variables must be defined as well.
template<typename T> ClassDefinition<T> ObjectWrap<T>::s_class; template<typename T> T ObjectWrap<T>::s_class;
} // jsc } // jsc

View File

@ -481,27 +481,27 @@ inline JSObjectRef jsc::Object::create_date(JSContextRef ctx, double time) {
} }
template<> template<>
template<typename U> template<typename ClassType>
inline JSObjectRef jsc::Object::create_instance(JSContextRef ctx, U* internal) { inline JSObjectRef jsc::Object::create_instance(JSContextRef ctx, typename ClassType::Internal* internal) {
return jsc::ObjectWrap<U>::create_instance(ctx, internal); return jsc::ObjectWrap<ClassType>::create_instance(ctx, internal);
} }
template<> template<>
template<typename U> template<typename ClassType>
inline bool jsc::Object::is_instance(JSContextRef ctx, const JSObjectRef &object) { inline bool jsc::Object::is_instance(JSContextRef ctx, const JSObjectRef &object) {
return jsc::ObjectWrap<U>::has_instance(ctx, object); return jsc::ObjectWrap<ClassType>::has_instance(ctx, object);
} }
template<> template<>
template<typename U> template<typename ClassType>
inline U* jsc::Object::get_internal(const JSObjectRef &object) { inline typename ClassType::Internal* jsc::Object::get_internal(const JSObjectRef &object) {
return *static_cast<jsc::ObjectWrap<U> *>(JSObjectGetPrivate(object)); return *static_cast<jsc::ObjectWrap<ClassType> *>(JSObjectGetPrivate(object));
} }
template<> template<>
template<typename U> template<typename ClassType>
inline void jsc::Object::set_internal(const JSObjectRef &object, U* ptr) { inline void jsc::Object::set_internal(const JSObjectRef &object, typename ClassType::Internal* ptr) {
auto wrap = static_cast<jsc::ObjectWrap<U> *>(JSObjectGetPrivate(object)); auto wrap = static_cast<jsc::ObjectWrap<ClassType> *>(JSObjectGetPrivate(object));
*wrap = ptr; *wrap = ptr;
} }

View File

@ -24,6 +24,7 @@
#include "rpc.hpp" #include "rpc.hpp"
#include "jsc_init.hpp" #include "jsc_init.hpp"
#include "jsc_types.hpp"
#include "js_object.hpp" #include "js_object.hpp"
#include "js_results.hpp" #include "js_results.hpp"
#include "js_realm.hpp" #include "js_realm.hpp"
@ -86,21 +87,21 @@ RPCServer::RPCServer() {
}; };
m_requests["/begin_transaction"] = [this](const json dict) { m_requests["/begin_transaction"] = [this](const json dict) {
RPCObjectID realm_id = dict["realmId"].get<RPCObjectID>(); RPCObjectID realm_id = dict["realmId"].get<RPCObjectID>();
SharedRealm realm = *jsc::Object::get_internal<SharedRealm>(m_objects[realm_id]); SharedRealm realm = *jsc::Object::get_internal<js::RealmClass<jsc::Types>>(m_objects[realm_id]);
realm->begin_transaction(); realm->begin_transaction();
return json::object(); return json::object();
}; };
m_requests["/cancel_transaction"] = [this](const json dict) { m_requests["/cancel_transaction"] = [this](const json dict) {
RPCObjectID realm_id = dict["realmId"].get<RPCObjectID>(); RPCObjectID realm_id = dict["realmId"].get<RPCObjectID>();
SharedRealm realm = *jsc::Object::get_internal<SharedRealm>(m_objects[realm_id]); SharedRealm realm = *jsc::Object::get_internal<js::RealmClass<jsc::Types>>(m_objects[realm_id]);
realm->cancel_transaction(); realm->cancel_transaction();
return json::object(); return json::object();
}; };
m_requests["/commit_transaction"] = [this](const json dict) { m_requests["/commit_transaction"] = [this](const json dict) {
RPCObjectID realm_id = dict["realmId"].get<RPCObjectID>(); RPCObjectID realm_id = dict["realmId"].get<RPCObjectID>();
SharedRealm realm = *jsc::Object::get_internal<SharedRealm>(m_objects[realm_id]); SharedRealm realm = *jsc::Object::get_internal<js::RealmClass<jsc::Types>>(m_objects[realm_id]);
realm->commit_transaction(); realm->commit_transaction();
return json::object(); return json::object();
@ -220,16 +221,16 @@ json RPCServer::serialize_json_value(JSValueRef js_value) {
JSObjectRef js_object = jsc::Value::validated_to_object(m_context, js_value); JSObjectRef js_object = jsc::Value::validated_to_object(m_context, js_value);
if (jsc::Object::is_instance<realm::Object>(m_context, js_object)) { if (jsc::Object::is_instance<js::RealmObjectClass<jsc::Types>>(m_context, js_object)) {
auto object = jsc::Object::get_internal<realm::Object>(js_object); auto object = jsc::Object::get_internal<js::RealmObjectClass<jsc::Types>>(js_object);
return { return {
{"type", RealmObjectTypesObject}, {"type", RealmObjectTypesObject},
{"id", store_object(js_object)}, {"id", store_object(js_object)},
{"schema", serialize_object_schema(object->get_object_schema())} {"schema", serialize_object_schema(object->get_object_schema())}
}; };
} }
else if (jsc::Object::is_instance<realm::List>(m_context, js_object)) { else if (jsc::Object::is_instance<js::ListClass<jsc::Types>>(m_context, js_object)) {
auto list = jsc::Object::get_internal<realm::List>(js_object); auto list = jsc::Object::get_internal<js::ListClass<jsc::Types>>(js_object);
return { return {
{"type", RealmObjectTypesList}, {"type", RealmObjectTypesList},
{"id", store_object(js_object)}, {"id", store_object(js_object)},
@ -237,8 +238,8 @@ json RPCServer::serialize_json_value(JSValueRef js_value) {
{"schema", serialize_object_schema(list->get_object_schema())} {"schema", serialize_object_schema(list->get_object_schema())}
}; };
} }
else if (jsc::Object::is_instance<realm::Results>(m_context, js_object)) { else if (jsc::Object::is_instance<js::ResultsClass<jsc::Types>>(m_context, js_object)) {
auto results = jsc::Object::get_internal<realm::Results>(js_object); auto results = jsc::Object::get_internal<js::ResultsClass<jsc::Types>>(js_object);
return { return {
{"type", RealmObjectTypesResults}, {"type", RealmObjectTypesResults},
{"id", store_object(js_object)}, {"id", store_object(js_object)},